You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2016/11/10 11:33:12 UTC

[01/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Repository: lucenenet
Updated Branches:
  refs/heads/grouping [created] 96d38effd


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/TestTreeSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestTreeSet.cs b/src/Lucene.Net.Tests/core/Support/TestTreeSet.cs
new file mode 100644
index 0000000..448e27c
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/TestTreeSet.cs
@@ -0,0 +1,2970 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using Lucene.Net.Attributes;
+using Lucene.Net.Support.C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.RBTreeSet
+{
+    using CollectionOfInt = TreeSet<int>;
+
+    [TestFixture]
+    public class GenericTesters
+    {
+        [Test, LuceneNetSpecific]
+        public void TestEvents()
+        {
+            Func<CollectionOfInt> factory = delegate () { return new CollectionOfInt(TenEqualityComparer.Default); };
+            new Templates.Events.SortedIndexedTester<CollectionOfInt>().Test(factory, MemoryType.Normal);
+        }
+
+        //[Test, LuceneNetSpecific]
+        //public void Extensible()
+        //{
+        //    C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+        //    C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+        //}
+    }
+
+    static class Factory
+    {
+        public static ICollection<T> New<T>() { return new TreeSet<T>(); }
+    }
+
+
+    [TestFixture]
+    public class Formatting
+    {
+        ICollection<int> coll;
+        IFormatProvider rad16;
+        [SetUp]
+        public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+        [TearDown]
+        public void Dispose() { coll = null; rad16 = null; }
+        [Test, LuceneNetSpecific]
+        public void Format()
+        {
+            Assert.AreEqual("{  }", coll.ToString());
+            coll.AddAll(new int[] { -4, 28, 129, 65530 });
+            Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString());
+            Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16));
+            Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null));
+            Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16));
+        }
+    }
+
+    [TestFixture]
+    public class Combined
+    {
+        private IIndexedSorted<KeyValuePair<int, int>> lst;
+
+
+        [SetUp]
+        public void Init()
+        {
+            lst = new TreeSet<KeyValuePair<int, int>>(new KeyValuePairComparer<int, int>(new IC()));
+            for (int i = 0; i < 10; i++)
+                lst.Add(new KeyValuePair<int, int>(i, i + 30));
+        }
+
+
+        [TearDown]
+        public void Dispose() { lst = null; }
+
+
+        [Test, LuceneNetSpecific]
+        public void Find()
+        {
+            KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+            Assert.IsTrue(lst.Find(ref p));
+            Assert.AreEqual(3, p.Key);
+            Assert.AreEqual(33, p.Value);
+            p = new KeyValuePair<int, int>(13, 78);
+            Assert.IsFalse(lst.Find(ref p));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void FindOrAdd()
+        {
+            KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+            Assert.IsTrue(lst.FindOrAdd(ref p));
+            Assert.AreEqual(3, p.Key);
+            Assert.AreEqual(33, p.Value);
+            p = new KeyValuePair<int, int>(13, 79);
+            Assert.IsFalse(lst.FindOrAdd(ref p));
+            Assert.AreEqual(13, lst[10].Key);
+            Assert.AreEqual(79, lst[10].Value);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Update()
+        {
+            KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+            Assert.IsTrue(lst.Update(p));
+            Assert.AreEqual(3, lst[3].Key);
+            Assert.AreEqual(78, lst[3].Value);
+            p = new KeyValuePair<int, int>(13, 78);
+            Assert.IsFalse(lst.Update(p));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void UpdateOrAdd1()
+        {
+            KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+            Assert.IsTrue(lst.UpdateOrAdd(p));
+            Assert.AreEqual(3, lst[3].Key);
+            Assert.AreEqual(78, lst[3].Value);
+            p = new KeyValuePair<int, int>(13, 79);
+            Assert.IsFalse(lst.UpdateOrAdd(p));
+            Assert.AreEqual(13, lst[10].Key);
+            Assert.AreEqual(79, lst[10].Value);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void UpdateOrAdd2()
+        {
+            ICollection<String> coll = new TreeSet<String>();
+            // s1 and s2 are distinct objects but contain the same text:
+            String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+            Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+            Assert.AreEqual(null, old);
+            Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+            Assert.IsTrue(Object.ReferenceEquals(s1, old));
+            Assert.IsFalse(Object.ReferenceEquals(s2, old));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void RemoveWithReturn()
+        {
+            KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+            Assert.IsTrue(lst.Remove(p, out p));
+            Assert.AreEqual(3, p.Key);
+            Assert.AreEqual(33, p.Value);
+            Assert.AreEqual(4, lst[3].Key);
+            Assert.AreEqual(34, lst[3].Value);
+            p = new KeyValuePair<int, int>(13, 78);
+            Assert.IsFalse(lst.Remove(p, out p));
+        }
+    }
+
+
+    [TestFixture]
+    public class Ranges
+    {
+        private TreeSet<int> tree;
+
+        private SCG.IComparer<int> c;
+
+
+        [SetUp]
+        public void Init()
+        {
+            c = new IC();
+            tree = new TreeSet<int>(c);
+            for (int i = 1; i <= 10; i++)
+            {
+                tree.Add(i * 2);
+            }
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Enumerator()
+        {
+            SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+            int i = 3;
+
+            while (e.MoveNext())
+            {
+                Assert.AreEqual(2 * i++, e.Current);
+            }
+
+            Assert.AreEqual(9, i);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Enumerator2()
+        {
+            SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+            Assert.Throws<InvalidOperationException>(() => { int i = e.Current; });
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Enumerator3()
+        {
+            SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+
+            while (e.MoveNext()) ;
+
+            Assert.Throws<InvalidOperationException>(() => { int i = e.Current; });
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Remove()
+        {
+            int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+
+            tree.RemoveRangeFrom(18);
+            Assert.IsTrue(IC.eq(tree, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 }));
+            tree.RemoveRangeFrom(28);
+            Assert.IsTrue(IC.eq(tree, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 }));
+            tree.RemoveRangeFrom(2);
+            Assert.IsTrue(IC.eq(tree));
+            foreach (int i in all) tree.Add(i);
+
+            tree.RemoveRangeTo(10);
+            Assert.IsTrue(IC.eq(tree, new int[] { 10, 12, 14, 16, 18, 20 }));
+            tree.RemoveRangeTo(2);
+            Assert.IsTrue(IC.eq(tree, new int[] { 10, 12, 14, 16, 18, 20 }));
+            tree.RemoveRangeTo(21);
+            Assert.IsTrue(IC.eq(tree));
+            foreach (int i in all) tree.Add(i);
+
+            tree.RemoveRangeFromTo(4, 8);
+            Assert.IsTrue(IC.eq(tree, 2, 8, 10, 12, 14, 16, 18, 20));
+            tree.RemoveRangeFromTo(14, 28);
+            Assert.IsTrue(IC.eq(tree, 2, 8, 10, 12));
+            tree.RemoveRangeFromTo(0, 9);
+            Assert.IsTrue(IC.eq(tree, 10, 12));
+            tree.RemoveRangeFromTo(0, 81);
+            Assert.IsTrue(IC.eq(tree));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Normal()
+        {
+            int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+
+            Assert.IsTrue(IC.eq(tree, all));
+            Assert.IsTrue(IC.eq(tree.RangeAll(), all));
+            Assert.AreEqual(10, tree.RangeAll().Count);
+            Assert.IsTrue(IC.eq(tree.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 }));
+            Assert.AreEqual(5, tree.RangeFrom(11).Count);
+            Assert.IsTrue(IC.eq(tree.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 }));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(2), all));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(1), all));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(21), new int[] { }));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(20), new int[] { 20 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(8), new int[] { 2, 4, 6 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(7), new int[] { 2, 4, 6 }));
+            Assert.AreEqual(3, tree.RangeTo(7).Count);
+            Assert.IsTrue(IC.eq(tree.RangeTo(2), new int[] { }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(1), new int[] { }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(3), new int[] { 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(20), new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(21), all));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(7, 12), new int[] { 8, 10 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 11), new int[] { 6, 8, 10 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(1, 12), new int[] { 2, 4, 6, 8, 10 }));
+            Assert.AreEqual(5, tree.RangeFromTo(1, 12).Count);
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(2, 12), new int[] { 2, 4, 6, 8, 10 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 21), new int[] { 6, 8, 10, 12, 14, 16, 18, 20 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 20), new int[] { 6, 8, 10, 12, 14, 16, 18 }));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Backwards()
+        {
+            int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+            int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 };
+
+            Assert.IsTrue(IC.eq(tree, all));
+            Assert.IsTrue(IC.eq(tree.RangeAll().Backwards(), lla));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(2).Backwards(), lla));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(1).Backwards(), lla));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(21).Backwards(), new int[] { }));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(20).Backwards(), new int[] { 20 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(8).Backwards(), new int[] { 6, 4, 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(7).Backwards(), new int[] { 6, 4, 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(2).Backwards(), new int[] { }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(1).Backwards(), new int[] { }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(3).Backwards(), new int[] { 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6, 4, 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeTo(21).Backwards(), lla));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(7, 12).Backwards(), new int[] { 10, 8 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 11).Backwards(), new int[] { 10, 8, 6 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(1, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(2, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 8, 6 }));
+            Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6 }));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Direction()
+        {
+            Assert.AreEqual(EnumerationDirection.Forwards, tree.Direction);
+            Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeFrom(20).Direction);
+            Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeTo(7).Direction);
+            Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeFromTo(1, 12).Direction);
+            Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeAll().Direction);
+            Assert.AreEqual(EnumerationDirection.Backwards, tree.Backwards().Direction);
+            Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeFrom(20).Backwards().Direction);
+            Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeTo(7).Backwards().Direction);
+            Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeFromTo(1, 12).Backwards().Direction);
+            Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeAll().Backwards().Direction);
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+            c = null;
+        }
+    }
+
+    [TestFixture]
+    public class BagItf
+    {
+        private TreeSet<int> tree;
+
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+            for (int i = 10; i < 20; i++)
+            {
+                tree.Add(i);
+                tree.Add(i + 10);
+            }
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Both()
+        {
+            Assert.AreEqual(0, tree.ContainsCount(7));
+            Assert.AreEqual(1, tree.ContainsCount(10));
+            tree.RemoveAllCopies(10);
+            Assert.AreEqual(0, tree.ContainsCount(10));
+            tree.RemoveAllCopies(7);
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+        }
+    }
+
+
+    [TestFixture]
+    public class Div
+    {
+        private TreeSet<int> tree;
+
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+        }
+
+
+        private void loadup()
+        {
+            for (int i = 10; i < 20; i++)
+            {
+                tree.Add(i);
+                tree.Add(i + 10);
+            }
+        }
+
+        [Test, LuceneNetSpecific]
+        public void NullEqualityComparerinConstructor1()
+        {
+            Assert.Throws<NullReferenceException>(() => new TreeSet<int>(null));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void NullEqualityComparerinConstructor3()
+        {
+            Assert.Throws<NullReferenceException>(() => new TreeSet<int>(null, EqualityComparer<int>.Default));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void NullEqualityComparerinConstructor4()
+        {
+            Assert.Throws<NullReferenceException>(() => new TreeSet<int>(SCG.Comparer<int>.Default, null));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void NullEqualityComparerinConstructor5()
+        {
+            Assert.Throws<NullReferenceException>(() => new TreeSet<int>(null, null));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Choose()
+        {
+            tree.Add(7);
+            Assert.AreEqual(7, tree.Choose());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void BadChoose()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.Choose());
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void NoDuplicates()
+        {
+            Assert.IsFalse(tree.AllowsDuplicates);
+            loadup();
+            Assert.IsFalse(tree.AllowsDuplicates);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Add()
+        {
+            Assert.IsTrue(tree.Add(17));
+            Assert.IsFalse(tree.Add(17));
+            Assert.IsTrue(tree.Add(18));
+            Assert.IsFalse(tree.Add(18));
+            Assert.AreEqual(2, tree.Count);
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+        }
+    }
+
+
+    [TestFixture]
+    public class FindOrAdd
+    {
+        private TreeSet<KeyValuePair<int, string>> bag;
+
+
+        [SetUp]
+        public void Init()
+        {
+            bag = new TreeSet<KeyValuePair<int, string>>(new KeyValuePairComparer<int, string>(new IC()));
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            bag = null;
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Test()
+        {
+            KeyValuePair<int, string> p = new KeyValuePair<int, string>(3, "tre");
+
+            Assert.IsFalse(bag.FindOrAdd(ref p));
+            p.Value = "drei";
+            Assert.IsTrue(bag.FindOrAdd(ref p));
+            Assert.AreEqual("tre", p.Value);
+            p.Value = "three";
+            Assert.AreEqual(1, bag.ContainsCount(p));
+            Assert.AreEqual("tre", bag[0].Value);
+        }
+    }
+
+    [TestFixture]
+    public class FindPredicate
+    {
+        private TreeSet<int> list;
+        Func<int, bool> pred;
+
+        [SetUp]
+        public void Init()
+        {
+            list = new TreeSet<int>(TenEqualityComparer.Default);
+            pred = delegate (int i) { return i % 5 == 0; };
+        }
+
+        [TearDown]
+        public void Dispose() { list = null; }
+
+        [Test, LuceneNetSpecific]
+        public void Find()
+        {
+            int i;
+            Assert.IsFalse(list.Find(pred, out i));
+            list.AddAll(new int[] { 4, 22, 67, 37 });
+            Assert.IsFalse(list.Find(pred, out i));
+            list.AddAll(new int[] { 45, 122, 675, 137 });
+            Assert.IsTrue(list.Find(pred, out i));
+            Assert.AreEqual(45, i);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindLast()
+        {
+            int i;
+            Assert.IsFalse(list.FindLast(pred, out i));
+            list.AddAll(new int[] { 4, 22, 67, 37 });
+            Assert.IsFalse(list.FindLast(pred, out i));
+            list.AddAll(new int[] { 45, 122, 675, 137 });
+            Assert.IsTrue(list.FindLast(pred, out i));
+            Assert.AreEqual(675, i);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindIndex()
+        {
+            Assert.IsFalse(0 <= list.FindIndex(pred));
+            list.AddAll(new int[] { 4, 22, 67, 37 });
+            Assert.IsFalse(0 <= list.FindIndex(pred));
+            list.AddAll(new int[] { 45, 122, 675, 137 });
+            Assert.AreEqual(3, list.FindIndex(pred));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindLastIndex()
+        {
+            Assert.IsFalse(0 <= list.FindLastIndex(pred));
+            list.AddAll(new int[] { 4, 22, 67, 37 });
+            Assert.IsFalse(0 <= list.FindLastIndex(pred));
+            list.AddAll(new int[] { 45, 122, 675, 137 });
+            Assert.AreEqual(7, list.FindLastIndex(pred));
+        }
+    }
+
+    [TestFixture]
+    public class UniqueItems
+    {
+        private TreeSet<int> list;
+
+        [SetUp]
+        public void Init() { list = new TreeSet<int>(); }
+
+        [TearDown]
+        public void Dispose() { list = null; }
+
+        [Test, LuceneNetSpecific]
+        public void Test()
+        {
+            Assert.IsTrue(IC.seteq(list.UniqueItems()));
+            Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+            list.AddAll(new int[] { 7, 9, 7 });
+            Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+            Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 1, 9, 1));
+        }
+    }
+
+    [TestFixture]
+    public class ArrayTest
+    {
+        private TreeSet<int> tree;
+
+        int[] a;
+
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+            a = new int[10];
+            for (int i = 0; i < 10; i++)
+                a[i] = 1000 + i;
+        }
+
+
+        [TearDown]
+        public void Dispose() { tree = null; }
+
+
+        private string aeq(int[] a, params int[] b)
+        {
+            if (a.Length != b.Length)
+            {
+                return "Lengths differ: " + a.Length + " != " + b.Length;
+            }
+
+            for (int i = 0; i < a.Length; i++)
+            {
+                if (a[i] != b[i])
+                {
+                    return string.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+                }
+            }
+            return "Alles klar";
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void ToArray()
+        {
+            Assert.AreEqual("Alles klar", aeq(tree.ToArray()));
+            tree.Add(7);
+            tree.Add(4);
+            Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 7));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void CopyTo()
+        {
+            tree.CopyTo(a, 1);
+            Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+            tree.Add(6);
+            tree.CopyTo(a, 2);
+            Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+            tree.Add(4);
+            tree.Add(9);
+            tree.CopyTo(a, 4);
+            Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009));
+            tree.Clear();
+            tree.Add(7);
+            tree.CopyTo(a, 9);
+            Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void CopyToBad()
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(() => tree.CopyTo(a, 11));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void CopyToBad2()
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(() => tree.CopyTo(a, -1));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void CopyToTooFar()
+        {
+            tree.Add(3);
+            tree.Add(4);
+            Assert.Throws<ArgumentOutOfRangeException>(() => tree.CopyTo(a, 9));
+        }
+    }
+
+    [TestFixture]
+    public class Remove
+    {
+        private TreeSet<int> tree;
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+            for (int i = 10; i < 20; i++)
+            {
+                tree.Add(i);
+                tree.Add(i + 10);
+            }
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void SmallTrees()
+        {
+            tree.Clear();
+            tree.Add(7);
+            tree.Add(9);
+            Assert.IsTrue(tree.Remove(7));
+            Assert.IsTrue(tree.Check(""));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void ByIndex()
+        {
+            //Remove root!
+            int n = tree.Count;
+            int i = tree[10];
+
+            tree.RemoveAt(10);
+            Assert.IsTrue(tree.Check(""));
+            Assert.IsFalse(tree.Contains(i));
+            Assert.AreEqual(n - 1, tree.Count);
+
+            //Low end
+            i = tree.FindMin();
+            tree.RemoveAt(0);
+            Assert.IsTrue(tree.Check(""));
+            Assert.IsFalse(tree.Contains(i));
+            Assert.AreEqual(n - 2, tree.Count);
+
+            //high end
+            i = tree.FindMax();
+            tree.RemoveAt(tree.Count - 1);
+            Assert.IsTrue(tree.Check(""));
+            Assert.IsFalse(tree.Contains(i));
+            Assert.AreEqual(n - 3, tree.Count);
+
+            //Some leaf
+            i = 18;
+            tree.RemoveAt(7);
+            Assert.IsTrue(tree.Check(""));
+            Assert.IsFalse(tree.Contains(i));
+            Assert.AreEqual(n - 4, tree.Count);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void AlmostEmpty()
+        {
+            //Almost empty
+            tree.Clear();
+            tree.Add(3);
+            tree.RemoveAt(0);
+            Assert.IsTrue(tree.Check(""));
+            Assert.IsFalse(tree.Contains(3));
+            Assert.AreEqual(0, tree.Count);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Empty()
+        {
+            tree.Clear();
+            var exception = Assert.Throws<IndexOutOfRangeException>(() => tree.RemoveAt(0));
+            Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void HighIndex()
+        {
+            var exception = Assert.Throws<IndexOutOfRangeException>(() => tree.RemoveAt(tree.Count));
+            Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void LowIndex()
+        {
+            var exception = Assert.Throws<IndexOutOfRangeException>(() => tree.RemoveAt(-1));
+            Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Normal()
+        {
+            Assert.IsFalse(tree.Remove(-20));
+
+            //No demote case, with move_item
+            Assert.IsTrue(tree.Remove(20));
+            Assert.IsTrue(tree.Check("T1"));
+            Assert.IsFalse(tree.Remove(20));
+
+            //plain case 2
+            Assert.IsTrue(tree.Remove(14));
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+            //case 1b
+            Assert.IsTrue(tree.Remove(25));
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+            //case 1c
+            Assert.IsTrue(tree.Remove(29));
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+            //1a (terminating)
+            Assert.IsTrue(tree.Remove(10));
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+            //2+1b
+            Assert.IsTrue(tree.Remove(12));
+            Assert.IsTrue(tree.Remove(11));
+
+            //1a+1b
+            Assert.IsTrue(tree.Remove(18));
+            Assert.IsTrue(tree.Remove(13));
+            Assert.IsTrue(tree.Remove(15));
+
+            //2+1c
+            for (int i = 0; i < 10; i++)
+                tree.Add(50 - 2 * i);
+
+            Assert.IsTrue(tree.Remove(42));
+            Assert.IsTrue(tree.Remove(38));
+            Assert.IsTrue(tree.Remove(28));
+            Assert.IsTrue(tree.Remove(40));
+
+            //
+            Assert.IsTrue(tree.Remove(16));
+            Assert.IsTrue(tree.Remove(23));
+            Assert.IsTrue(tree.Remove(17));
+            Assert.IsTrue(tree.Remove(19));
+            Assert.IsTrue(tree.Remove(50));
+            Assert.IsTrue(tree.Remove(26));
+            Assert.IsTrue(tree.Remove(21));
+            Assert.IsTrue(tree.Remove(22));
+            Assert.IsTrue(tree.Remove(24));
+            for (int i = 0; i < 48; i++)
+                tree.Remove(i);
+
+            //Almost empty tree:
+            Assert.IsFalse(tree.Remove(26));
+            Assert.IsTrue(tree.Remove(48));
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+            //Empty tree:
+            Assert.IsFalse(tree.Remove(26));
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+        }
+    }
+
+
+
+    [TestFixture]
+    public class PredecessorStructure
+    {
+        private TreeSet<int> tree;
+
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+        }
+
+
+        private void loadup()
+        {
+            for (int i = 0; i < 20; i++)
+                tree.Add(2 * i);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindPredecessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryPredecessor(7, out res) && res == 6);
+            Assert.IsTrue(tree.TryPredecessor(8, out res) && res == 6);
+
+            //The bottom
+            Assert.IsTrue(tree.TryPredecessor(1, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryPredecessor(39, out res) && res == 38);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindPredecessorTooLow1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryPredecessor(-2, out res));
+            Assert.AreEqual(0, res);
+            Assert.IsFalse(tree.TryPredecessor(0, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindWeakPredecessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryWeakPredecessor(7, out res) && res == 6);
+            Assert.IsTrue(tree.TryWeakPredecessor(8, out res) && res == 8);
+
+            //The bottom
+            Assert.IsTrue(tree.TryWeakPredecessor(1, out res) && res == 0);
+            Assert.IsTrue(tree.TryWeakPredecessor(0, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryWeakPredecessor(39, out res) && res == 38);
+            Assert.IsTrue(tree.TryWeakPredecessor(38, out res) && res == 38);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindWeakPredecessorTooLow1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryWeakPredecessor(-1, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindSuccessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TrySuccessor(7, out res) && res == 8);
+            Assert.IsTrue(tree.TrySuccessor(8, out res) && res == 10);
+
+            //The bottom
+            Assert.IsTrue(tree.TrySuccessor(0, out res) && res == 2);
+            Assert.IsTrue(tree.TrySuccessor(-1, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TrySuccessor(37, out res) && res == 38);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindSuccessorTooHigh()
+        {
+            int res;
+            Assert.IsFalse(tree.TrySuccessor(38, out res));
+            Assert.AreEqual(0, res);
+            Assert.IsFalse(tree.TrySuccessor(39, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindWeakSuccessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryWeakSuccessor(6, out res) && res == 6);
+            Assert.IsTrue(tree.TryWeakSuccessor(7, out res) && res == 8);
+
+            //The bottom
+            Assert.IsTrue(tree.TryWeakSuccessor(-1, out res) && res == 0);
+            Assert.IsTrue(tree.TryWeakSuccessor(0, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryWeakSuccessor(37, out res) && res == 38);
+            Assert.IsTrue(tree.TryWeakSuccessor(38, out res) && res == 38);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void FindWeakSuccessorTooHigh1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryWeakSuccessor(39, out res));
+            Assert.AreEqual(0, res);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Predecessor()
+        {
+            loadup();
+            Assert.AreEqual(6, tree.Predecessor(7));
+            Assert.AreEqual(6, tree.Predecessor(8));
+
+            //The bottom
+            Assert.AreEqual(0, tree.Predecessor(1));
+
+            //The top
+            Assert.AreEqual(38, tree.Predecessor(39));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void PredecessorTooLow1()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.Predecessor(-2));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void PredecessorTooLow2()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.Predecessor(0));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void WeakPredecessor()
+        {
+            loadup();
+            Assert.AreEqual(6, tree.WeakPredecessor(7));
+            Assert.AreEqual(8, tree.WeakPredecessor(8));
+
+            //The bottom
+            Assert.AreEqual(0, tree.WeakPredecessor(1));
+            Assert.AreEqual(0, tree.WeakPredecessor(0));
+
+            //The top
+            Assert.AreEqual(38, tree.WeakPredecessor(39));
+            Assert.AreEqual(38, tree.WeakPredecessor(38));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void WeakPredecessorTooLow1()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.WeakPredecessor(-2));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Successor()
+        {
+            loadup();
+            Assert.AreEqual(8, tree.Successor(7));
+            Assert.AreEqual(10, tree.Successor(8));
+
+            //The bottom
+            Assert.AreEqual(2, tree.Successor(0));
+            Assert.AreEqual(0, tree.Successor(-1));
+
+            //The top
+            Assert.AreEqual(38, tree.Successor(37));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void SuccessorTooHigh1()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.Successor(38));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void SuccessorTooHigh2()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.Successor(39));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void WeakSuccessor()
+        {
+            loadup();
+            Assert.AreEqual(6, tree.WeakSuccessor(6));
+            Assert.AreEqual(8, tree.WeakSuccessor(7));
+
+            //The bottom
+            Assert.AreEqual(0, tree.WeakSuccessor(-1));
+            Assert.AreEqual(0, tree.WeakSuccessor(0));
+
+            //The top
+            Assert.AreEqual(38, tree.WeakSuccessor(37));
+            Assert.AreEqual(38, tree.WeakSuccessor(38));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void WeakSuccessorTooHigh1()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.WeakSuccessor(39));
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+        }
+    }
+
+    [TestFixture]
+    public class PriorityQueue
+    {
+        private TreeSet<int> tree;
+
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+        }
+
+        private void loadup()
+        {
+            foreach (int i in new int[] { 1, 2, 3, 4 })
+                tree.Add(i);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Normal()
+        {
+            loadup();
+            Assert.AreEqual(1, tree.FindMin());
+            Assert.AreEqual(4, tree.FindMax());
+            Assert.AreEqual(1, tree.DeleteMin());
+            Assert.AreEqual(4, tree.DeleteMax());
+            Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+            Assert.AreEqual(2, tree.FindMin());
+            Assert.AreEqual(3, tree.FindMax());
+            Assert.AreEqual(2, tree.DeleteMin());
+            Assert.AreEqual(3, tree.DeleteMax());
+            Assert.IsTrue(tree.Check("Normal test 2"), "Bad tree");
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Empty1()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.FindMin());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Empty2()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.FindMax());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Empty3()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.DeleteMin());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Empty4()
+        {
+            Assert.Throws<NoSuchItemException>(() => tree.DeleteMax());
+        }
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+        }
+    }
+
+    [TestFixture]
+    public class IndexingAndCounting
+    {
+        private TreeSet<int> tree;
+
+        [SetUp]
+        public void Init()
+        {
+            tree = new TreeSet<int>(new IC());
+        }
+
+        private void populate()
+        {
+            tree.Add(30);
+            tree.Add(50);
+            tree.Add(10);
+            tree.Add(70);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void ToArray()
+        {
+            populate();
+
+            int[] a = tree.ToArray();
+
+            Assert.AreEqual(4, a.Length);
+            Assert.AreEqual(10, a[0]);
+            Assert.AreEqual(30, a[1]);
+            Assert.AreEqual(50, a[2]);
+            Assert.AreEqual(70, a[3]);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void GoodIndex()
+        {
+            Assert.AreEqual(-1, tree.IndexOf(20));
+            Assert.AreEqual(-1, tree.LastIndexOf(20));
+            populate();
+            Assert.AreEqual(10, tree[0]);
+            Assert.AreEqual(30, tree[1]);
+            Assert.AreEqual(50, tree[2]);
+            Assert.AreEqual(70, tree[3]);
+            Assert.AreEqual(0, tree.IndexOf(10));
+            Assert.AreEqual(1, tree.IndexOf(30));
+            Assert.AreEqual(2, tree.IndexOf(50));
+            Assert.AreEqual(3, tree.IndexOf(70));
+            Assert.AreEqual(~1, tree.IndexOf(20));
+            Assert.AreEqual(~0, tree.IndexOf(0));
+            Assert.AreEqual(~4, tree.IndexOf(90));
+            Assert.AreEqual(0, tree.LastIndexOf(10));
+            Assert.AreEqual(1, tree.LastIndexOf(30));
+            Assert.AreEqual(2, tree.LastIndexOf(50));
+            Assert.AreEqual(3, tree.LastIndexOf(70));
+            Assert.AreEqual(~1, tree.LastIndexOf(20));
+            Assert.AreEqual(~0, tree.LastIndexOf(0));
+            Assert.AreEqual(~4, tree.LastIndexOf(90));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void IndexTooLarge()
+        {
+            populate();
+            Assert.Throws<IndexOutOfRangeException>(() => Console.WriteLine(tree[4]));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void IndexTooSmall()
+        {
+            populate();
+            Assert.Throws<IndexOutOfRangeException>(() => Console.WriteLine(tree[-1]));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void FilledTreeOutsideInput()
+        {
+            populate();
+            Assert.AreEqual(0, tree.CountFrom(90));
+            Assert.AreEqual(0, tree.CountFromTo(-20, 0));
+            Assert.AreEqual(0, tree.CountFromTo(80, 100));
+            Assert.AreEqual(0, tree.CountTo(0));
+            Assert.AreEqual(4, tree.CountTo(90));
+            Assert.AreEqual(4, tree.CountFromTo(-20, 90));
+            Assert.AreEqual(4, tree.CountFrom(0));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void FilledTreeIntermediateInput()
+        {
+            populate();
+            Assert.AreEqual(3, tree.CountFrom(20));
+            Assert.AreEqual(1, tree.CountFromTo(20, 40));
+            Assert.AreEqual(2, tree.CountTo(40));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void FilledTreeMatchingInput()
+        {
+            populate();
+            Assert.AreEqual(3, tree.CountFrom(30));
+            Assert.AreEqual(2, tree.CountFromTo(30, 70));
+            Assert.AreEqual(0, tree.CountFromTo(50, 30));
+            Assert.AreEqual(0, tree.CountFromTo(50, 50));
+            Assert.AreEqual(0, tree.CountTo(10));
+            Assert.AreEqual(2, tree.CountTo(50));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void CountEmptyTree()
+        {
+            Assert.AreEqual(0, tree.CountFrom(20));
+            Assert.AreEqual(0, tree.CountFromTo(20, 40));
+            Assert.AreEqual(0, tree.CountTo(40));
+        }
+
+        [TearDown]
+        public void Dispose()
+        {
+            tree = null;
+        }
+    }
+
+    namespace ModificationCheck
+    {
+        [TestFixture]
+        public class Enumerator
+        {
+            private TreeSet<int> tree;
+
+            private SCG.IEnumerator<int> e;
+
+
+            [SetUp]
+            public void Init()
+            {
+                tree = new TreeSet<int>(new IC());
+                for (int i = 0; i < 10; i++)
+                    tree.Add(i);
+
+                e = tree.GetEnumerator();
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void CurrentAfterModification()
+            {
+                e.MoveNext();
+                tree.Add(34);
+                Assert.AreEqual(0, e.Current);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void MoveNextAfterAdd()
+            {
+                tree.Add(34);
+
+                Assert.Throws<CollectionModifiedException>(() => e.MoveNext());
+            }
+
+            [Test, LuceneNetSpecific]
+            public void MoveNextAfterRemove()
+            {
+                tree.Remove(34);
+
+                Assert.Throws<CollectionModifiedException>(() => e.MoveNext());
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void MoveNextAfterClear()
+            {
+                tree.Clear();
+
+                Assert.Throws<CollectionModifiedException>(() => e.MoveNext());
+            }
+
+
+            [TearDown]
+            public void Dispose()
+            {
+                tree = null;
+                e = null;
+            }
+        }
+
+        [TestFixture]
+        public class RangeEnumerator
+        {
+            private TreeSet<int> tree;
+
+            private SCG.IEnumerator<int> e;
+
+            [SetUp]
+            public void Init()
+            {
+                tree = new TreeSet<int>(new IC());
+                for (int i = 0; i < 10; i++)
+                    tree.Add(i);
+
+                e = tree.RangeFromTo(3, 7).GetEnumerator();
+            }
+
+            [Test, LuceneNetSpecific]
+            public void CurrentAfterModification()
+            {
+                e.MoveNext();
+                tree.Add(34);
+                Assert.AreEqual(3, e.Current);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void MoveNextAfterAdd()
+            {
+                tree.Add(34);
+
+                Assert.Throws<CollectionModifiedException>(() => e.MoveNext());
+            }
+
+            [Test, LuceneNetSpecific]
+            public void MoveNextAfterRemove()
+            {
+                tree.Remove(34);
+
+                Assert.Throws<CollectionModifiedException>(() => e.MoveNext());
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void MoveNextAfterClear()
+            {
+                tree.Clear();
+
+                Assert.Throws<CollectionModifiedException>(() => e.MoveNext());
+            }
+
+
+            [TearDown]
+            public void Dispose()
+            {
+                tree = null;
+                e = null;
+            }
+        }
+    }
+
+    namespace PathcopyPersistence
+    {
+        [TestFixture]
+        public class Navigation
+        {
+            private TreeSet<int> tree, snap;
+
+            private SCG.IComparer<int> ic;
+
+            [SetUp]
+            public void Init()
+            {
+                ic = new IC();
+                tree = new TreeSet<int>(ic);
+                for (int i = 0; i <= 20; i++)
+                    tree.Add(2 * i + 1);
+
+                snap = (TreeSet<int>)tree.Snapshot();
+                for (int i = 0; i <= 10; i++)
+                    tree.Remove(4 * i + 1);
+            }
+
+
+            private bool twomodeleven(int i)
+            {
+                return i % 11 == 2;
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void InternalEnum()
+            {
+                Assert.IsTrue(IC.eq(snap.FindAll(new Func<int, bool>(twomodeleven)), 13, 35));
+            }
+
+
+            public void MoreCut() { }
+
+            [Test, LuceneNetSpecific]
+            public void Cut()
+            {
+                int lo, hi;
+                bool lv, hv;
+
+                Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(64), out lo, out lv, out hi, out hv));
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(5, hi);
+                Assert.AreEqual(3, lo);
+                Assert.IsTrue(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv));
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(7, hi);
+                Assert.AreEqual(3, lo);
+                Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out hi, out hv));
+                Assert.IsTrue(lv && !hv);
+                Assert.AreEqual(41, lo);
+                Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(-27), out lo, out lv, out hi, out hv));
+                Assert.IsTrue(!lv && hv);
+                Assert.AreEqual(1, hi);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Range()
+            {
+                Assert.IsTrue(IC.eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 15));
+                Assert.IsTrue(IC.eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 15));
+                Assert.IsTrue(IC.eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 15));
+                //Assert.AreEqual(snap.RangeFromTo(6, 16).Count, 5);
+            }
+
+            [Test, LuceneNetSpecific]
+            public void Contains()
+            {
+                Assert.IsTrue(snap.Contains(5));
+            }
+
+            [Test, LuceneNetSpecific]
+            public void FindMin()
+            {
+                Assert.AreEqual(1, snap.FindMin());
+            }
+
+            [Test, LuceneNetSpecific]
+            public void FindMax()
+            {
+                Assert.AreEqual(41, snap.FindMax());
+            }
+
+            [Test, LuceneNetSpecific]
+            public void FindPredecessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TryPredecessor(15, out res) && res == 13);
+                Assert.IsTrue(snap.TryPredecessor(16, out res) && res == 15);
+                Assert.IsTrue(snap.TryPredecessor(17, out res) && res == 15);
+                Assert.IsTrue(snap.TryPredecessor(18, out res) && res == 17);
+
+                Assert.IsTrue(snap.TryPredecessor(2, out res) && res == 1);
+
+                Assert.IsFalse(snap.TryPredecessor(1, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void FindSuccessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TrySuccessor(15, out res) && res == 17);
+                Assert.IsTrue(snap.TrySuccessor(16, out res) && res == 17);
+                Assert.IsTrue(snap.TrySuccessor(17, out res) && res == 19);
+                Assert.IsTrue(snap.TrySuccessor(18, out res) && res == 19);
+
+                Assert.IsTrue(snap.TrySuccessor(40, out res) && res == 41);
+
+                Assert.IsFalse(snap.TrySuccessor(41, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void FindWeakPredecessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TryWeakPredecessor(15, out res) && res == 15);
+                Assert.IsTrue(snap.TryWeakPredecessor(16, out res) && res == 15);
+                Assert.IsTrue(snap.TryWeakPredecessor(17, out res) && res == 17);
+                Assert.IsTrue(snap.TryWeakPredecessor(18, out res) && res == 17);
+
+                Assert.IsTrue(snap.TryWeakPredecessor(1, out res) && res == 1);
+
+                Assert.IsFalse(snap.TryWeakPredecessor(0, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void FindWeakSuccessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TryWeakSuccessor(15, out res) && res == 15);
+                Assert.IsTrue(snap.TryWeakSuccessor(16, out res) && res == 17);
+                Assert.IsTrue(snap.TryWeakSuccessor(17, out res) && res == 17);
+                Assert.IsTrue(snap.TryWeakSuccessor(18, out res) && res == 19);
+
+                Assert.IsTrue(snap.TryWeakSuccessor(41, out res) && res == 41);
+
+                Assert.IsFalse(snap.TryWeakSuccessor(42, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Predecessor()
+            {
+                Assert.AreEqual(13, snap.Predecessor(15));
+                Assert.AreEqual(15, snap.Predecessor(16));
+                Assert.AreEqual(15, snap.Predecessor(17));
+                Assert.AreEqual(17, snap.Predecessor(18));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Successor()
+            {
+                Assert.AreEqual(17, snap.Successor(15));
+                Assert.AreEqual(17, snap.Successor(16));
+                Assert.AreEqual(19, snap.Successor(17));
+                Assert.AreEqual(19, snap.Successor(18));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void WeakPredecessor()
+            {
+                Assert.AreEqual(15, snap.WeakPredecessor(15));
+                Assert.AreEqual(15, snap.WeakPredecessor(16));
+                Assert.AreEqual(17, snap.WeakPredecessor(17));
+                Assert.AreEqual(17, snap.WeakPredecessor(18));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void WeakSuccessor()
+            {
+                Assert.AreEqual(15, snap.WeakSuccessor(15));
+                Assert.AreEqual(17, snap.WeakSuccessor(16));
+                Assert.AreEqual(17, snap.WeakSuccessor(17));
+                Assert.AreEqual(19, snap.WeakSuccessor(18));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void CountTo()
+            {
+                var exception = Assert.Throws<NotSupportedException>(() =>
+                {
+                    int j = snap.CountTo(15);
+                });
+                Assert.AreEqual("Indexing not supported for snapshots", exception.Message);
+            }
+
+            [Test, LuceneNetSpecific]
+            public void Indexing()
+            {
+                var exception = Assert.Throws<NotSupportedException>(() =>
+                {
+                    int j = snap[4];
+                });
+                Assert.AreEqual("Indexing not supported for snapshots", exception.Message);
+            }
+
+            [Test, LuceneNetSpecific]
+            public void Indexing2()
+            {
+                var exception = Assert.Throws<NotSupportedException>(() =>
+                {
+                    int j = snap.IndexOf(5);
+                });
+                Assert.AreEqual("Indexing not supported for snapshots", exception.Message);
+            }
+
+            [TearDown]
+            public void Dispose()
+            {
+                tree = null;
+                ic = null;
+            }
+        }
+
+        [TestFixture]
+        public class Single
+        {
+            private TreeSet<int> tree;
+
+            private SCG.IComparer<int> ic;
+
+
+            [SetUp]
+            public void Init()
+            {
+                ic = new IC();
+                tree = new TreeSet<int>(ic);
+                for (int i = 0; i < 10; i++)
+                    tree.Add(2 * i + 1);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void EnumerationWithAdd()
+            {
+                int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+                int i = 0;
+                TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+                foreach (int j in snap)
+                {
+                    Assert.AreEqual(1 + 2 * i++, j);
+                    tree.Add(21 - j);
+                    Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                    Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                    Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+                }
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Remove()
+            {
+                int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+                TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                tree.Remove(19);
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RemoveNormal()
+            {
+                tree.Clear();
+                for (int i = 10; i < 20; i++)
+                {
+                    tree.Add(i);
+                    tree.Add(i + 10);
+                }
+
+                int[] orig = new int[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 };
+                TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+                Assert.IsFalse(tree.Remove(-20));
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //No demote case, with move_item
+                Assert.IsTrue(tree.Remove(20));
+                Assert.IsTrue(tree.Check("T1"));
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.IsFalse(tree.Remove(20));
+
+                //plain case 2
+                tree.Snapshot();
+                Assert.IsTrue(tree.Remove(14));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //case 1b
+                Assert.IsTrue(tree.Remove(25));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //case 1c
+                Assert.IsTrue(tree.Remove(29));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //1a (terminating)
+                Assert.IsTrue(tree.Remove(10));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //2+1b
+                Assert.IsTrue(tree.Remove(12));
+                tree.Snapshot();
+                Assert.IsTrue(tree.Remove(11));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //1a+1b
+                Assert.IsTrue(tree.Remove(18));
+                Assert.IsTrue(tree.Remove(13));
+                Assert.IsTrue(tree.Remove(15));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //2+1c
+                for (int i = 0; i < 10; i++)
+                    tree.Add(50 - 2 * i);
+
+                Assert.IsTrue(tree.Remove(42));
+                Assert.IsTrue(tree.Remove(38));
+                Assert.IsTrue(tree.Remove(28));
+                Assert.IsTrue(tree.Remove(40));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //
+                Assert.IsTrue(tree.Remove(16));
+                Assert.IsTrue(tree.Remove(23));
+                Assert.IsTrue(tree.Remove(17));
+                Assert.IsTrue(tree.Remove(19));
+                Assert.IsTrue(tree.Remove(50));
+                Assert.IsTrue(tree.Remove(26));
+                Assert.IsTrue(tree.Remove(21));
+                Assert.IsTrue(tree.Remove(22));
+                Assert.IsTrue(tree.Remove(24));
+                for (int i = 0; i < 48; i++)
+                    tree.Remove(i);
+
+                //Almost empty tree:
+                Assert.IsFalse(tree.Remove(26));
+                Assert.IsTrue(tree.Remove(48));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+                //Empty tree:
+                Assert.IsFalse(tree.Remove(26));
+                Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Add()
+            {
+                int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+                TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+                Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+                tree.Add(10);
+                Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+                tree.Add(16);
+                Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+
+                //Promote+zigzig
+                tree.Add(40);
+                Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                for (int i = 1; i < 4; i++)
+                    tree.Add(40 - 2 * i);
+
+                Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+
+                //Zigzag:
+                tree.Add(32);
+                Assert.IsTrue(snap.Check("M"), "Bad snap!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Clear()
+            {
+                int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+                TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+                tree.Clear();
+                Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+                Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+                Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+                Assert.AreEqual(0, tree.Count);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void SnapSnap()
+            {
+                TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+                var exception = Assert.Throws<InvalidOperationException>(() => snap.Snapshot());
+                Assert.AreEqual("Cannot snapshot a snapshot", exception.Message);
+            }
+
+            [TearDown]
+            public void Dispose()
+            {
+                tree = null;
+                ic = null;
+            }
+        }
+
+        [TestFixture]
+        public class Multiple
+        {
+            private TreeSet<int> tree;
+
+            private SCG.IComparer<int> ic;
+
+            private bool eq(SCG.IEnumerable<int> me, int[] that)
+            {
+                int i = 0, maxind = that.Length - 1;
+
+                foreach (int item in me)
+                    if (i > maxind || ic.Compare(item, that[i++]) != 0)
+                        return false;
+
+                return true;
+            }
+
+            [SetUp]
+            public void Init()
+            {
+                ic = new IC();
+                tree = new TreeSet<int>(ic);
+                for (int i = 0; i < 10; i++)
+                    tree.Add(2 * i + 1);
+            }
+
+            [Test, LuceneNetSpecific]
+            public void First()
+            {
+                TreeSet<int>[] snaps = new TreeSet<int>[10];
+
+                for (int i = 0; i < 10; i++)
+                {
+                    snaps[i] = (TreeSet<int>)(tree.Snapshot());
+                    tree.Add(2 * i);
+                }
+
+                for (int i = 0; i < 10; i++)
+                {
+                    Assert.AreEqual(i + 10, snaps[i].Count);
+                }
+
+                snaps[5] = null;
+                snaps[9] = null;
+                GC.Collect();
+                snaps[8].Dispose();
+                tree.Remove(14);
+
+                int[] res = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19 };
+                int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 };
+                int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 };
+
+                Assert.IsTrue(IC.eq(snaps[3], snap3), "Snap 3 was changed!");
+                Assert.IsTrue(IC.eq(snaps[7], snap7), "Snap 7 was changed!");
+                Assert.IsTrue(IC.eq(tree, res));
+                Assert.IsTrue(tree.Check("B"));
+                Assert.IsTrue(snaps[3].Check("B"));
+                Assert.IsTrue(snaps[7].Check("B"));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void CollectingTheMaster()
+            {
+                TreeSet<int>[] snaps = new TreeSet<int>[10];
+
+                for (int i = 0; i < 10; i++)
+                {
+                    snaps[i] = (TreeSet<int>)(tree.Snapshot());
+                    tree.Add(2 * i);
+                }
+
+                tree = null;
+                GC.Collect();
+                for (int i = 0; i < 10; i++)
+                {
+                    Assert.AreEqual(i + 10, snaps[i].Count);
+                }
+
+                snaps[5] = null;
+                snaps[9] = null;
+                GC.Collect();
+                snaps[8].Dispose();
+
+                int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 };
+                int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 };
+
+                Assert.IsTrue(IC.eq(snaps[3], snap3), "Snap 3 was changed!");
+                Assert.IsTrue(IC.eq(snaps[7], snap7), "Snap 7 was changed!");
+                Assert.IsTrue(snaps[3].Check("B"));
+                Assert.IsTrue(snaps[7].Check("B"));
+            }
+
+
+            [TearDown]
+            public void Dispose()
+            {
+                tree = null;
+                ic = null;
+            }
+        }
+    }
+
+
+
+
+    namespace HigherOrder
+    {
+        internal class CubeRoot : IComparable<int>
+        {
+            private int c;
+
+
+            internal CubeRoot(int c) { this.c = c; }
+
+
+            public int CompareTo(int that) { return c - that * that * that; }
+            public bool Equals(int that) { return c == that * that * that; }
+        }
+
+
+
+        class Interval : IComparable<int>
+        {
+            private int b, t;
+
+
+            internal Interval(int b, int t) { this.b = b; this.t = t; }
+
+
+            public int CompareTo(int that) { return that < b ? 1 : that > t ? -1 : 0; }
+            public bool Equals(int that) { return that >= b && that <= t; }
+        }
+
+
+
+        [TestFixture]
+        public class Simple
+        {
+            private TreeSet<int> tree;
+
+            private SCG.IComparer<int> ic;
+
+
+            [SetUp]
+            public void Init()
+            {
+                ic = new IC();
+                tree = new TreeSet<int>(ic);
+            }
+
+
+            private bool never(int i) { return false; }
+
+
+            private bool always(int i) { return true; }
+
+
+            private bool even(int i) { return i % 2 == 0; }
+
+
+            private string themap(int i) { return string.Format("AA {0,4} BB", i); }
+
+
+            private string badmap(int i) { return string.Format("AA {0} BB", i); }
+
+
+            private int appfield1;
+
+            private int appfield2;
+
+
+            private void apply(int i) { appfield1++; appfield2 += i * i; }
+
+
+            [Test, LuceneNetSpecific]
+            public void Apply()
+            {
+                Simple simple1 = new Simple();
+
+                tree.Apply(new Action<int>(simple1.apply));
+                Assert.AreEqual(0, simple1.appfield1);
+                Assert.AreEqual(0, simple1.appfield2);
+
+                Simple simple2 = new Simple();
+
+                for (int i = 0; i < 10; i++) tree.Add(i);
+
+                tree.Apply(new Action<int>(simple2.apply));
+                Assert.AreEqual(10, simple2.appfield1);
+                Assert.AreEqual(285, simple2.appfield2);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void All()
+            {
+                Assert.IsTrue(tree.All(new Func<int, bool>(never)));
+                Assert.IsTrue(tree.All(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.All(new Func<int, bool>(always)));
+                for (int i = 0; i < 10; i++) tree.Add(i);
+
+                Assert.IsFalse(tree.All(new Func<int, bool>(never)));
+                Assert.IsFalse(tree.All(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.All(new Func<int, bool>(always)));
+                tree.Clear();
+                for (int i = 0; i < 10; i++) tree.Add(i * 2);
+
+                Assert.IsFalse(tree.All(new Func<int, bool>(never)));
+                Assert.IsTrue(tree.All(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.All(new Func<int, bool>(always)));
+                tree.Clear();
+                for (int i = 0; i < 10; i++) tree.Add(i * 2 + 1);
+
+                Assert.IsFalse(tree.All(new Func<int, bool>(never)));
+                Assert.IsFalse(tree.All(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.All(new Func<int, bool>(always)));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Exists()
+            {
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(never)));
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(even)));
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(always)));
+                for (int i = 0; i < 10; i++) tree.Add(i);
+
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(never)));
+                Assert.IsTrue(tree.Exists(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.Exists(new Func<int, bool>(always)));
+                tree.Clear();
+                for (int i = 0; i < 10; i++) tree.Add(i * 2);
+
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(never)));
+                Assert.IsTrue(tree.Exists(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.Exists(new Func<int, bool>(always)));
+                tree.Clear();
+                for (int i = 0; i < 10; i++) tree.Add(i * 2 + 1);
+
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(never)));
+                Assert.IsFalse(tree.Exists(new Func<int, bool>(even)));
+                Assert.IsTrue(tree.Exists(new Func<int, bool>(always)));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void FindAll()
+            {
+                Assert.AreEqual(0, tree.FindAll(new Func<int, bool>(never)).Count);
+                for (int i = 0; i < 10; i++)
+                    tree.Add(i);
+
+                Assert.AreEqual(0, tree.FindAll(new Func<int, bool>(never)).Count);
+                Assert.AreEqual(10, tree.FindAll(new Func<int, bool>(always)).Count);
+                Assert.AreEqual(5, tree.FindAll(new Func<int, bool>(even)).Count);
+                Assert.IsTrue(((TreeSet<int>)tree.FindAll(new Func<int, bool>(even))).Check("R"));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Map()
+            {
+                Assert.AreEqual(0, tree.Map(new Func<int, string>(themap), new SC()).Count);
+                for (int i = 0; i < 11; i++)
+                    tree.Add(i * i * i);
+
+                IIndexedSorted<string> res = tree.Map(new Func<int, string>(themap), new SC());
+
+                Assert.IsTrue(((TreeSet<string>)res).Check("R"));
+                Assert.AreEqual(11, res.Count);
+                Assert.AreEqual("AA    0 BB", res[0]);
+                Assert.AreEqual("AA   27 BB", res[3]);
+                Assert.AreEqual("AA  125 BB", res[5]);
+                Assert.AreEqual("AA 1000 BB", res[10]);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void BadMap()
+            {
+                for (int i = 0; i < 11; i++)
+                {
+                    tree.Add(i * i * i);
+                }
+
+                var exception = Assert.Throws<ArgumentException>(() =>
+                {
+                    ISorted<string> res = tree.Map(new Func<int, string>(badmap), new SC());
+                });
+                Assert.AreEqual("mapper not monotonic", exception.Message);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Cut()
+            {
+                for (int i = 0; i < 10; i++)
+                    tree.Add(i);
+
+                int low, high;
+                bool lval, hval;
+
+                Assert.IsTrue(tree.Cut(new CubeRoot(27), out low, out lval, out high, out hval));
+                Assert.IsTrue(lval && hval);
+                Assert.AreEqual(4, high);
+                Assert.AreEqual(2, low);
+                Assert.IsFalse(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval));
+                Assert.IsTrue(lval && hval);
+                Assert.AreEqual(4, high);
+                Assert.AreEqual(3, low);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void CutInt()
+            {
+                for (int i = 0; i < 10; i++)
+                    tree.Add(2 * i);
+
+                int low, high;
+                bool lval, hval;
+
+                Assert.IsFalse(tree.Cut(new IC(3), out low, out lval, out high, out hval));
+                Assert.IsTrue(lval && hval);
+                Assert.AreEqual(4, high);
+                Assert.AreEqual(2, low);
+                Assert.IsTrue(tree.Cut(new IC(6), out low, out lval, out high, out hval));
+                Assert.IsTrue(lval && hval);
+                Assert.AreEqual(8, high);
+                Assert.AreEqual(4, low);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void CutInterval()
+            {
+                for (int i = 0; i < 10; i++)
+                    tree.Add(2 * i);
+
+                int lo, hi;
+                bool lv, hv;
+
+                Assert.IsTrue(tree.Cut(new Interval(5, 9), out lo, out lv, out hi, out hv));
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(10, hi);
+                Assert.AreEqual(4, lo);
+                Assert.IsTrue(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv));
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(12, hi);
+                Assert.AreEqual(4, lo);
+                for (int i = 0; i < 100; i++)
+                    tree.Add(2 * i);
+
+                tree.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv);
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(106, hi);
+                Assert.AreEqual(76, lo);
+                tree.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv);
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(8, hi);
+                Assert.AreEqual(4, lo);
+                tree.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv);
+                Assert.IsTrue(lv && hv);
+                Assert.AreEqual(112, hi);
+                Assert.AreEqual(78, lo);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void UpperCut()
+            {
+                for (int i = 0; i < 10; i++)
+                    tree.Add(i);
+
+                int l, h;
+                bool lv, hv;
+
+                Assert.IsFalse(tree.Cut(new CubeRoot(1000), out l, out lv, out h, out hv));
+                Assert.IsTrue(lv && !hv);
+                Assert.AreEqual(9, l);
+                Assert.IsFalse(tree.Cut(new CubeRoot(-50), out l, out lv, out h, out hv));
+                Assert.IsTrue(!lv && hv);
+                Assert.AreEqual(0, h);
+            }
+
+
+            [TearDown]
+            public void Dispose() { ic = null; tree = null; }
+        }
+    }
+
+
+
+
+    namespace MultiOps
+    {
+        [TestFixture]
+        public class AddAll
+        {
+            private int sqr(int i) { return i * i; }
+
+
+            TreeSet<int> tree;
+
+
+            [SetUp]
+            public void Init() { tree = new TreeSet<int>(new IC()); }
+
+
+            [Test, LuceneNetSpecific]
+            public void EmptyEmpty()
+            {
+                tree.AddAll(new FunEnumerable(0, new Func<int, int>(sqr)));
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(tree.Check());
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void SomeEmpty()
+            {
+                for (int i = 4; i < 9; i++) tree.Add(i);
+
+                tree.AddAll(new FunEnumerable(0, new Func<int, int>(sqr)));
+                Assert.AreEqual(5, tree.Count);
+                Assert.IsTrue(tree.Check());
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void EmptySome()
+            {
+                tree.AddAll(new FunEnumerable(4, new Func<int, int>(sqr)));
+                Assert.AreEqual(4, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.AreEqual(0, tree[0]);
+                Assert.AreEqual(1, tree[1]);
+                Assert.AreEqual(4, tree[2]);
+                Assert.AreEqual(9, tree[3]);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void SomeSome()
+            {
+                for (int i = 5; i < 9; i++) tree.Add(i);
+
+                tree.AddAll(new FunEnumerable(4, new Func<int, int>(sqr)));
+                Assert.AreEqual(8, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 0, 1, 4, 5, 6, 7, 8, 9));
+            }
+
+
+            [TearDown]
+            public void Dispose() { tree = null; }
+        }
+
+
+
+        [TestFixture]
+        public class AddSorted
+        {
+            private int sqr(int i) { return i * i; }
+
+
+            private int bad(int i) { return i * (5 - i); }
+
+
+            TreeSet<int> tree;
+
+
+            [SetUp]
+            public void Init() { tree = new TreeSet<int>(new IC()); }
+
+
+            [Test, LuceneNetSpecific]
+            public void EmptyEmpty()
+            {
+                tree.AddSorted(new FunEnumerable(0, new Func<int, int>(sqr)));
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(tree.Check());
+            }
+
+
+
+            [Test, LuceneNetSpecific]
+            public void SomeEmpty()
+            {
+                for (int i = 4; i < 9; i++) tree.Add(i);
+
+                tree.AddSorted(new FunEnumerable(0, new Func<int, int>(sqr)));
+                Assert.AreEqual(5, tree.Count);
+                Assert.IsTrue(tree.Check());
+            }
+
+
+
+            [Test, LuceneNetSpecific]
+            public void EmptySome()
+            {
+                tree.AddSorted(new FunEnumerable(4, new Func<int, int>(sqr)));
+                Assert.AreEqual(4, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.AreEqual(0, tree[0]);
+                Assert.AreEqual(1, tree[1]);
+                Assert.AreEqual(4, tree[2]);
+                Assert.AreEqual(9, tree[3]);
+            }
+
+
+
+            [Test, LuceneNetSpecific]
+            public void SomeSome()
+            {
+                for (int i = 5; i < 9; i++) tree.Add(i);
+
+                tree.AddSorted(new FunEnumerable(4, new Func<int, int>(sqr)));
+                Assert.AreEqual(8, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 0, 1, 4, 5, 6, 7, 8, 9));
+            }
+
+            [Test, LuceneNetSpecific]
+            public void EmptyBad()
+            {
+                var exception = Assert.Throws<ArgumentException>(() => tree.AddSorted(new FunEnumerable(9, new Func<int, int>(bad))));
+                Assert.AreEqual("Argument not sorted", exception.Message);
+            }
+
+
+            [TearDown]
+            public void Dispose() { tree = null; }
+        }
+
+        [TestFixture]
+        public class Rest
+        {
+            TreeSet<int> tree, tree2;
+
+
+            [SetUp]
+            public void Init()
+            {
+                tree = new TreeSet<int>(new IC());
+                tree2 = new TreeSet<int>(new IC());
+                for (int i = 0; i < 10; i++)
+                    tree.Add(i);
+
+                for (int i = 0; i < 10; i++)
+                    tree2.Add(2 * i);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RemoveAll()
+            {
+                tree.RemoveAll(tree2.RangeFromTo(3, 7));
+                Assert.AreEqual(8, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+                tree.RemoveAll(tree2.RangeFromTo(3, 7));
+                Assert.AreEqual(8, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+                tree.RemoveAll(tree2.RangeFromTo(13, 17));
+                Assert.AreEqual(8, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+                tree.RemoveAll(tree2.RangeFromTo(3, 17));
+                Assert.AreEqual(7, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 9));
+                for (int i = 0; i < 10; i++) tree2.Add(i);
+
+                tree.RemoveAll(tree2.RangeFromTo(-1, 10));
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RetainAll()
+            {
+                tree.RetainAll(tree2.RangeFromTo(3, 17));
+                Assert.AreEqual(3, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 4, 6, 8));
+                tree.RetainAll(tree2.RangeFromTo(1, 17));
+                Assert.AreEqual(3, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 4, 6, 8));
+                tree.RetainAll(tree2.RangeFromTo(3, 5));
+                Assert.AreEqual(1, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree, 4));
+                tree.RetainAll(tree2.RangeFromTo(7, 17));
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree));
+                for (int i = 0; i < 10; i++) tree.Add(i);
+
+                tree.RetainAll(tree2.RangeFromTo(5, 5));
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree));
+                for (int i = 0; i < 10; i++) tree.Add(i);
+
+                tree.RetainAll(tree2.RangeFromTo(15, 25));
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(tree.Check());
+                Assert.IsTrue(IC.eq(tree));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void ContainsAll()
+            {
+                Assert.IsFalse(tree.ContainsAll(tree2));
+                Assert.IsTrue(tree.ContainsAll(tree));
+                tree2.Clear();
+                Assert.IsTrue(tree.ContainsAll(tree2));
+                tree.Clear();
+                Assert.IsTrue(tree.ContainsAll(tree2));
+                tree2.Add(8);
+                Assert.IsFalse(tree.ContainsAll(tree2));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RemoveInterval()
+            {
+                tree.RemoveInterval(3, 4);
+                Assert.IsTrue(tree.Check());
+                Assert.AreEqual(6, tree.Count);
+                Assert.IsTrue(IC.eq(tree, 0, 1, 2, 7, 8, 9));
+                tree.RemoveInterval(2, 3);
+                Assert.IsTrue(tree.Check());
+                Assert.AreEqual(3, tree.Count);
+                Assert.IsTrue(IC.eq(tree, 0, 1, 9));
+                tree.RemoveInterval(0, 3);
+                Assert.IsTrue(tree.Check());
+                Assert.AreEqual(0, tree.Count);
+                Assert.IsTrue(IC.eq(tree));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RemoveRangeBad1()
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => tree.RemoveInterval(-3, 8));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RemoveRangeBad2()
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => tree.RemoveInterval(3, -8));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void RemoveRangeBad3()
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => tree.RemoveInterval(3, 8));
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void GetRange()
+            {
+                SCG.IEnumerable<int> e = tree[3, 3];
+                Assert.IsTrue(IC.eq(e, 3, 4, 5));
+                e = tree[3, 0];
+                Assert.IsTrue(IC.eq(e));
+            }
+
+            [Test, LuceneNetSpecific]
+            public void GetRangeBad1()
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() =>
+                {
+                    object foo = tree[-3, 0];
+                });
+            }
+
+            [Test, LuceneNetSpecific]
+            public void GetRangeBad2()
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() =>
+                {
+                    object foo = tree[3, -1];
+                });
+            }
+
+            [Test, LuceneNetSpecific]
+            public void GetRangeBad3()
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() =>
+                {
+                    object foo = tree[3, 8];
+                });
+            }
+
+            [TearDown]
+            public void Dispose() { tree = null; tree2 = null; }
+        }
+    }
+
+
+
+
+    namespace Sync
+    {
+        [TestFixture]
+        public class SyncRoot
+        {
+            private TreeSet<int> tree;
+            private readonly Object mySyncRoot = new Object();
+            int sz = 5000;
+
+
+            [Test, LuceneNetSpecific]
+            public void Safe()
+            {
+                System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(safe1));
+                System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(safe2));
+
+                t1.Start();
+                t2.Start();
+                t1.Join();
+                t2.Join();
+                Assert.AreEqual(2 * sz + 1, tree.Count);
+                Assert.IsTrue(tree.Check());
+            }
+
+
+            //[Test, LuceneNetSpecific]
+            public void UnSafe()
+            {
+                bool bad = false;
+
+                for (int i = 0; i < 10; i++)
+                {
+                    System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1));
+                    System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2));
+
+                    t1.Start();
+                    t2.Start();
+                    t1.Join();
+                    t2.Join();
+                    if (bad = 2 * sz + 1 != tree.Count)
+                    {
+                        Console.WriteLine("{0}::Unsafe(): bad at {1}", GetType(), i);
+                        break;
+                    }
+                }
+
+                Assert.IsTrue(bad, "No sync problems!");
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void SafeUnSafe()
+            {
+                System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1));
+                System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2));
+
+                t1.Start();
+                t1.Join();
+                t2.Start();
+                t2.Join();
+                Assert.AreEqual(2 * sz + 1, tree.Count);
+            }
+
+
+            [SetUp]
+            public void Init() { tree = new TreeSet<int>(new IC()); }
+
+
+            private void unsafe1()
+            {
+                for (int i = 0; i < 2 * sz; i++)
+                    tree.Add(i * 2);
+
+                for (int i = 1; i < sz; i++)
+                    tree.Remove(i * 4);
+            }
+
+
+            private void safe1()
+            {
+                for (int i = 0; i < 2 * sz; i++)
+                    lock (mySyncRoot)
+                        tree.Add(i * 2);
+
+                for (int i = 1; i < sz; i++)
+                    lock (mySyncRoot)
+                        tree.Remove(i * 4);
+            }
+
+
+            private void unsafe2()
+            {
+                for (int i = 2 * sz; i > 0; i--)
+                    tree.Add(i * 2 + 1);
+
+                for (int i = sz; i > 0; i--)
+                    tree.Remove(i * 4 + 1);
+            }
+
+
+            private void safe2()
+            {
+                for (int i = 2 * sz; i > 0; i--)
+                    lock (mySyncRoot)
+                        tree.Add(i * 2 + 1);
+
+                for (int i = sz; i > 0; i--)
+                    lock (mySyncRoot)
+                        tree.Remove(i * 4 + 1);
+            }
+
+
+            [TearDown]
+            public void Dispose() { tree = null; }
+        }
+
+
+
+        //[TestFixture]

<TRUNCATED>

[32/58] [abbrv] lucenenet git commit: WIP on Grouping

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
new file mode 100644
index 0000000..c50219d
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
@@ -0,0 +1,155 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Search;
+using Lucene.Net.Util.Mutable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping.Function
+{
+    /// <summary>
+    /// An implementation of <see cref="AbstractAllGroupHeadsCollector"/> for retrieving the most relevant groups when grouping
+    /// by <see cref="ValueSource"/>.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class FunctionAllGroupHeadsCollector : AbstractAllGroupHeadsCollector<FunctionAllGroupHeadsCollector.GroupHead>
+    {
+        private readonly ValueSource groupBy;
+        private readonly IDictionary /* Map<?, ?> */ vsContext;
+        private readonly IDictionary<MutableValue, GroupHead> groups;
+        private readonly Sort sortWithinGroup;
+
+        private FunctionValues.AbstractValueFiller filler;
+        private MutableValue mval;
+        private AtomicReaderContext readerContext;
+        private Scorer scorer;
+
+        /**
+         * Constructs a {@link FunctionAllGroupHeadsCollector} instance.
+         *
+         * @param groupBy The {@link ValueSource} to group by
+         * @param vsContext The ValueSource context
+         * @param sortWithinGroup The sort within a group
+         */
+        public FunctionAllGroupHeadsCollector(ValueSource groupBy, IDictionary /* Map<?, ?> */ vsContext, Sort sortWithinGroup)
+            : base(sortWithinGroup.GetSort().Length)
+        {
+            groups = new Dictionary<MutableValue, GroupHead>();
+            this.sortWithinGroup = sortWithinGroup;
+            this.groupBy = groupBy;
+            this.vsContext = vsContext;
+
+            SortField[] sortFields = sortWithinGroup.GetSort();
+            for (int i = 0; i < sortFields.Length; i++)
+            {
+                reversed[i] = sortFields[i].Reverse ? -1 : 1;
+            }
+        }
+
+        protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        {
+            filler.FillValue(doc);
+            GroupHead groupHead;
+            if (!groups.TryGetValue(mval, out groupHead))
+            {
+                MutableValue groupValue = mval.Duplicate();
+                groupHead = new GroupHead(this, groupValue, sortWithinGroup, doc);
+                groups[groupValue] = groupHead;
+                temporalResult.stop = true;
+            }
+            else
+            {
+                temporalResult.stop = false;
+            }
+            this.temporalResult.groupHead = groupHead;
+        }
+
+        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        {
+            return groups.Values;
+        }
+
+        public override Scorer Scorer
+        {
+            set
+            {
+                this.scorer = value;
+                foreach (GroupHead groupHead in groups.Values)
+                {
+                    foreach (FieldComparator comparator in groupHead.comparators)
+                    {
+                        comparator.Scorer = value;
+                    }
+                }
+            }
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                this.readerContext = value;
+                FunctionValues values = groupBy.GetValues(vsContext, value);
+                filler = values.ValueFiller;
+                mval = filler.Value;
+
+                foreach (GroupHead groupHead in groups.Values)
+                {
+                    for (int i = 0; i < groupHead.comparators.Length; i++)
+                    {
+                        groupHead.comparators[i] = groupHead.comparators[i].SetNextReader(value);
+                    }
+                }
+            }
+        }
+
+        /** Holds current head document for a single group.
+         *
+         * @lucene.experimental */
+        public class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<MutableValue>*/
+        {
+
+            private readonly FunctionAllGroupHeadsCollector outerInstance;
+            public readonly MutableValue groupValue;
+            internal readonly FieldComparator[] comparators;
+
+            internal GroupHead(FunctionAllGroupHeadsCollector outerInstance, MutableValue groupValue, Sort sort, int doc)
+                        /*: base(groupValue, doc + outerInstance.readerContext.DocBase)*/
+                        : base(doc + outerInstance.readerContext.DocBase)
+            {
+                this.outerInstance = outerInstance;
+                this.groupValue = groupValue;
+
+                SortField[] sortFields = sort.GetSort();
+                comparators = new FieldComparator[sortFields.Length];
+                for (int i = 0; i < sortFields.Length; i++)
+                {
+                    comparators[i] = sortFields[i].GetComparator(1, i).SetNextReader(outerInstance.readerContext);
+                    comparators[i].Scorer = outerInstance.scorer;
+                    comparators[i].Copy(0, doc);
+                    comparators[i].Bottom = 0;
+                }
+            }
+
+            public override int Compare(int compIDX, int doc)
+            {
+                return comparators[compIDX].CompareBottom(doc);
+            }
+
+            public override void UpdateDocHead(int doc)
+            {
+                foreach (FieldComparator comparator in comparators)
+                {
+                    comparator.Copy(0, doc);
+                    comparator.Bottom = 0;
+                }
+                this.Doc = doc + outerInstance.readerContext.DocBase;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
new file mode 100644
index 0000000..638f36b
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
@@ -0,0 +1,69 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Util.Mutable;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Search.Grouping.Function
+{
+    /// <summary>
+    /// A collector that collects all groups that match the
+    /// query. Only the group value is collected, and the order
+    /// is undefined.  This collector does not determine
+    /// the most relevant document of a group.
+    /// 
+    /// <para>
+    /// Implementation detail: Uses <see cref="ValueSource"/> and <see cref="FunctionValues"/> to retrieve the
+    /// field values to group by.
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
+    public class FunctionAllGroupsCollector : AbstractAllGroupsCollector<MutableValue>
+    {
+        private readonly IDictionary /* Map<?, ?> */ vsContext;
+        private readonly ValueSource groupBy;
+        private readonly SortedSet<MutableValue> groups = new SortedSet<MutableValue>();
+
+        private FunctionValues.AbstractValueFiller filler;
+        private MutableValue mval;
+
+        /**
+         * Constructs a {@link FunctionAllGroupsCollector} instance.
+         *
+         * @param groupBy The {@link ValueSource} to group by
+         * @param vsContext The ValueSource context
+         */
+        public FunctionAllGroupsCollector(ValueSource groupBy, IDictionary /* Map<?, ?> */ vsContext)
+        {
+            this.vsContext = vsContext;
+            this.groupBy = groupBy;
+        }
+
+        public override ICollection<MutableValue> Groups
+        {
+            get
+            {
+                return groups;
+            }
+        }
+
+        public override void Collect(int doc)
+        {
+            filler.FillValue(doc);
+            if (!groups.Contains(mval))
+            {
+                groups.Add(mval.Duplicate());
+            }
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                FunctionValues values = groupBy.GetValues(vsContext, value);
+                filler = values.ValueFiller;
+                mval = filler.Value;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
new file mode 100644
index 0000000..2e84920
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
@@ -0,0 +1,85 @@
+\ufeffusing Lucene.Net.Queries.Function;
+using Lucene.Net.Support;
+using Lucene.Net.Util.Mutable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Lucene.Net.Index;
+
+namespace Lucene.Net.Search.Grouping.Function
+{
+    /// <summary>
+    /// Function based implementation of <see cref="AbstractDistinctValuesCollector"/>.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class FunctionDistinctValuesCollector : AbstractDistinctValuesCollector<FunctionDistinctValuesCollector.GroupCount>
+    {
+        private readonly IDictionary /* Map<?, ?> */ vsContext;
+        private readonly ValueSource groupSource;
+        private readonly ValueSource countSource;
+        private readonly IDictionary<MutableValue, GroupCount> groupMap;
+
+        private FunctionValues.AbstractValueFiller groupFiller;
+        private FunctionValues.AbstractValueFiller countFiller;
+        private MutableValue groupMval;
+        private MutableValue countMval;
+
+        public FunctionDistinctValuesCollector(IDictionary /*Map<?, ?>*/ vsContext, ValueSource groupSource, ValueSource countSource, ICollection<SearchGroup<MutableValue>> groups)
+        {
+            this.vsContext = vsContext;
+            this.groupSource = groupSource;
+            this.countSource = countSource;
+            groupMap = new LurchTable<MutableValue, GroupCount>(1 << 4);
+            foreach (SearchGroup<MutableValue> group in groups)
+            {
+                groupMap[group.groupValue] = new GroupCount(group.groupValue);
+            }
+        }
+
+        public override List<GroupCount> GetGroups()
+        {
+            return new List<GroupCount>(groupMap.Values);
+        }
+
+        public override void Collect(int doc)
+        {
+            groupFiller.FillValue(doc);
+            GroupCount groupCount;
+            if (groupMap.TryGetValue(groupMval, out groupCount))
+            {
+                countFiller.FillValue(doc);
+                groupCount.uniqueValues.Add(countMval.Duplicate());
+            }
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                FunctionValues values = groupSource.GetValues(vsContext, value);
+                groupFiller = values.ValueFiller;
+                groupMval = groupFiller.Value;
+                values = countSource.GetValues(vsContext, value);
+                countFiller = values.ValueFiller;
+                countMval = countFiller.Value;
+            }
+        }
+
+
+
+        /** Holds distinct values for a single group.
+         *
+         * @lucene.experimental */
+        public class GroupCount : AbstractGroupCount<MutableValue> /*AbstractDistinctValuesCollector.GroupCount<MutableValue>*/
+        {
+            internal GroupCount(MutableValue groupValue)
+                : base(groupValue)
+            {
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
new file mode 100644
index 0000000..18f9fb6
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
@@ -0,0 +1,71 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Util.Mutable;
+using System.Collections;
+
+namespace Lucene.Net.Search.Grouping.Function
+{
+    /// <summary>
+    /// Concrete implementation of <see cref="AbstractFirstPassGroupingCollector{TGroupValue}"/> that groups based on
+    /// <see cref="ValueSource"/> instances.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class FunctionFirstPassGroupingCollector : AbstractFirstPassGroupingCollector<MutableValue>
+    {
+        private readonly ValueSource groupByVS;
+        private readonly IDictionary /* Map<?, ?> */ vsContext;
+
+        private FunctionValues.AbstractValueFiller filler;
+        private MutableValue mval;
+
+        /// <summary>
+        /// Creates a first pass collector.
+        /// </summary>
+        /// <param name="groupByVS">The <see cref="ValueSource"/> instance to group by</param>
+        /// <param name="vsContext">The <see cref="ValueSource"/> context</param>
+        /// <param name="groupSort">
+        /// The <see cref="Sort"/> used to sort the
+        /// groups.  The top sorted document within each group
+        /// according to groupSort, determines how that group
+        /// sorts against other groups.  This must be non-null,
+        /// ie, if you want to groupSort by relevance use
+        /// <see cref="Sort.RELEVANCE"/>.
+        /// </param>
+        /// <param name="topNGroups">How many top groups to keep.</param>
+        /// <exception cref="IOException">When I/O related errors occur</exception>
+        public FunctionFirstPassGroupingCollector(ValueSource groupByVS, IDictionary /* Map<?, ?> */ vsContext, Sort groupSort, int topNGroups)
+            : base(groupSort, topNGroups)
+        {
+            this.groupByVS = groupByVS;
+            this.vsContext = vsContext;
+        }
+
+        protected override MutableValue GetDocGroupValue(int doc)
+        {
+            filler.FillValue(doc);
+            return mval;
+        }
+
+        protected override MutableValue CopyDocGroupValue(MutableValue groupValue, MutableValue reuse)
+        {
+            if (reuse != null)
+            {
+                reuse.Copy(groupValue);
+                return reuse;
+            }
+            return groupValue.Duplicate();
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                base.NextReader = value;
+                FunctionValues values = groupByVS.GetValues(vsContext, value);
+                filler = values.ValueFiller;
+                mval = filler.Value;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
new file mode 100644
index 0000000..23f04b0
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
@@ -0,0 +1,64 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Util.Mutable;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Search.Grouping.Function
+{
+    /// <summary>
+    /// Concrete implementation of <see cref="AbstractSecondPassGroupingCollector{TGroupValue}"/> that groups based on
+    /// <see cref="ValueSource"/> instances.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class FunctionSecondPassGroupingCollector : AbstractSecondPassGroupingCollector<MutableValue>
+    {
+        private readonly ValueSource groupByVS;
+        private readonly IDictionary /* Map<?, ?> */ vsContext;
+
+        private FunctionValues.AbstractValueFiller filler;
+        private MutableValue mval;
+
+        /// <summary>
+        /// Constructs a <see cref="FunctionSecondPassGroupingCollector"/> instance.
+        /// </summary>
+        /// <param name="searchGroups">The <see cref="SearchGroup{TGroupValue}"/> instances collected during the first phase.</param>
+        /// <param name="groupSort">The group sort</param>
+        /// <param name="withinGroupSort">The sort inside a group</param>
+        /// <param name="maxDocsPerGroup">The maximum number of documents to collect inside a group</param>
+        /// <param name="getScores">Whether to include the scores</param>
+        /// <param name="getMaxScores">Whether to include the maximum score</param>
+        /// <param name="fillSortFields">Whether to fill the sort values in <see cref="TopGroups{TGroupValueType}.WithinGroupSort"/></param>
+        /// <param name="groupByVS">The <see cref="ValueSource"/> to group by</param>
+        /// <param name="vsContext">The value source context</param>
+        /// <exception cref="IOException">When I/O related errors occur</exception>
+        public FunctionSecondPassGroupingCollector(ICollection<SearchGroup<MutableValue>> searchGroups, 
+            Sort groupSort, Sort withinGroupSort, int maxDocsPerGroup, bool getScores, bool getMaxScores, 
+            bool fillSortFields, ValueSource groupByVS, IDictionary /* Map<?, ?> */ vsContext)
+            : base(searchGroups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields)
+        {
+            this.groupByVS = groupByVS;
+            this.vsContext = vsContext;
+        }
+
+        protected override AbstractSecondPassGroupingCollector.SearchGroupDocs<MutableValue> RetrieveGroup(int doc)
+        {
+            filler.FillValue(doc);
+            AbstractSecondPassGroupingCollector.SearchGroupDocs<MutableValue> result;
+            groupMap.TryGetValue(mval, out result);
+            return result;
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                base.NextReader = value;
+                FunctionValues values = groupByVS.GetValues(vsContext, value);
+                filler = values.ValueFiller;
+                mval = filler.Value;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/GroupDocs.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupDocs.cs b/src/Lucene.Net.Grouping/GroupDocs.cs
index 00cdf83..29d227e 100644
--- a/src/Lucene.Net.Grouping/GroupDocs.cs
+++ b/src/Lucene.Net.Grouping/GroupDocs.cs
@@ -1,6 +1,6 @@
 \ufeffusing Lucene.Net.Search;
 
-namespace Lucene.Net.Grouping
+namespace Lucene.Net.Search.Grouping
 {
     /*
 	 * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -24,13 +24,13 @@ namespace Lucene.Net.Grouping
     /// 
     /// @lucene.experimental 
     /// </summary>
-    public class GroupDocs<TGroupValueType>
+    public class GroupDocs<TGroupValue>
     {
         /// <summary>
         /// The groupField value for all docs in this group; this
         /// may be null if hits did not have the groupField. 
         /// </summary>
-        public readonly TGroupValueType GroupValue;
+        public readonly TGroupValue GroupValue;
 
         /// <summary>
         /// Max score in this group
@@ -58,7 +58,7 @@ namespace Lucene.Net.Grouping
         /// </summary>
         public readonly object[] GroupSortValues;
 
-        public GroupDocs(float score, float maxScore, int totalHits, ScoreDoc[] scoreDocs, TGroupValueType groupValue, object[] groupSortValues)
+        public GroupDocs(float score, float maxScore, int totalHits, ScoreDoc[] scoreDocs, TGroupValue groupValue, object[] groupSortValues)
         {
             Score = score;
             MaxScore = maxScore;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/GroupingSearch.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupingSearch.cs b/src/Lucene.Net.Grouping/GroupingSearch.cs
new file mode 100644
index 0000000..28b5381
--- /dev/null
+++ b/src/Lucene.Net.Grouping/GroupingSearch.cs
@@ -0,0 +1,483 @@
+\ufeffusing Lucene.Net.Queries.Function;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Grouping;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Search.Grouping.Terms;
+using Lucene.Net.Util;
+using Lucene.Net.Util.Mutable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// Convenience class to perform grouping in a non distributed environment.
+    /// @lucene.experimental
+    /// </summary>
+    public class GroupingSearch
+    {
+        private readonly string groupField;
+        private readonly ValueSource groupFunction;
+        private readonly IDictionary /* Map<?, ?> */ valueSourceContext;
+        private readonly Filter groupEndDocs;
+
+        private Sort groupSort = Sort.RELEVANCE;
+        private Sort sortWithinGroup;
+
+        private int groupDocsOffset;
+        private int groupDocsLimit = 1;
+        private bool fillSortFields;
+        private bool includeScores = true;
+        private bool includeMaxScore = true;
+
+        private double? maxCacheRAMMB;
+        private int? maxDocsToCache;
+        private bool cacheScores;
+        private bool allGroups;
+        private bool allGroupHeads;
+        private int initialSize = 128;
+
+        private ICollection /* Collection<?> */ matchingGroups;
+        private Bits matchingGroupHeads;
+
+        /**
+         * Constructs a <code>GroupingSearch</code> instance that groups documents by index terms using the {@link FieldCache}.
+         * The group field can only have one token per document. This means that the field must not be analysed.
+         *
+         * @param groupField The name of the field to group by.
+         */
+        public GroupingSearch(string groupField)
+            : this(groupField, null, null, null)
+        {
+        }
+
+        /**
+         * Constructs a <code>GroupingSearch</code> instance that groups documents by function using a {@link ValueSource}
+         * instance.
+         *
+         * @param groupFunction      The function to group by specified as {@link ValueSource}
+         * @param valueSourceContext The context of the specified groupFunction
+         */
+        public GroupingSearch(ValueSource groupFunction, IDictionary /* Map<?, ?> */ valueSourceContext)
+            : this(null, groupFunction, valueSourceContext, null)
+        {
+
+        }
+
+        /**
+         * Constructor for grouping documents by doc block.
+         * This constructor can only be used when documents belonging in a group are indexed in one block.
+         *
+         * @param groupEndDocs The filter that marks the last document in all doc blocks
+         */
+        public GroupingSearch(Filter groupEndDocs)
+            : this(null, null, null, groupEndDocs)
+        {
+        }
+
+        private GroupingSearch(string groupField, ValueSource groupFunction, IDictionary /* Map<?, ?> */ valueSourceContext, Filter groupEndDocs)
+        {
+            this.groupField = groupField;
+            this.groupFunction = groupFunction;
+            this.valueSourceContext = valueSourceContext;
+            this.groupEndDocs = groupEndDocs;
+        }
+
+        /**
+         * Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
+         *
+         * @param searcher    The {@link org.apache.lucene.search.IndexSearcher} instance to execute the grouped search on.
+         * @param query       The query to execute with the grouping
+         * @param groupOffset The group offset
+         * @param groupLimit  The number of groups to return from the specified group offset
+         * @return the grouped result as a {@link TopGroups} instance
+         * @throws IOException If any I/O related errors occur
+         */
+        public TopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+        {
+            return Search<TGroupValue>(searcher, null, query, groupOffset, groupLimit);
+        }
+
+        /**
+         * Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
+         *
+         * @param searcher    The {@link org.apache.lucene.search.IndexSearcher} instance to execute the grouped search on.
+         * @param filter      The filter to execute with the grouping
+         * @param query       The query to execute with the grouping
+         * @param groupOffset The group offset
+         * @param groupLimit  The number of groups to return from the specified group offset
+         * @return the grouped result as a {@link TopGroups} instance
+         * @throws IOException If any I/O related errors occur
+         */
+        public TopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        {
+            if (groupField != null || groupFunction != null)
+            {
+                return GroupByFieldOrFunction<TGroupValue>(searcher, filter, query, groupOffset, groupLimit);
+            }
+            else if (groupEndDocs != null)
+            {
+                return (TopGroups<TGroupValue>)GroupByDocBlock<TGroupValue>(searcher, filter, query, groupOffset, groupLimit);
+            }
+            else
+            {
+                throw new InvalidOperationException("Either groupField, groupFunction or groupEndDocs must be set."); // This can't happen...
+            }
+        }
+
+        protected TopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        {
+            // LUCENENET TODO: Finish
+            return null;
+            //int topN = groupOffset + groupLimit;
+            //AbstractFirstPassGroupingCollector<TGroupValue> firstPassCollector;
+            //AbstractAllGroupsCollector<TGroupValue> allGroupsCollector;
+            //AbstractAllGroupHeadsCollector allGroupHeadsCollector;
+            //if (groupFunction != null)
+            //{
+            //    firstPassCollector = new FunctionFirstPassGroupingCollector(groupFunction, valueSourceContext, groupSort, topN);
+            //    if (allGroups)
+            //    {
+            //        allGroupsCollector = new FunctionAllGroupsCollector(groupFunction, valueSourceContext);
+            //    }
+            //    else
+            //    {
+            //        allGroupsCollector = null;
+            //    }
+            //    if (allGroupHeads)
+            //    {
+            //        allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(groupFunction, valueSourceContext, sortWithinGroup);
+            //    }
+            //    else
+            //    {
+            //        allGroupHeadsCollector = null;
+            //    }
+            //}
+            //else
+            //{
+            //    firstPassCollector = new TermFirstPassGroupingCollector(groupField, groupSort, topN);
+            //    if (allGroups)
+            //    {
+            //        allGroupsCollector = new TermAllGroupsCollector(groupField, initialSize);
+            //    }
+            //    else
+            //    {
+            //        allGroupsCollector = null;
+            //    }
+            //    if (allGroupHeads)
+            //    {
+            //        allGroupHeadsCollector = TermAllGroupHeadsCollector.Create(groupField, sortWithinGroup, initialSize);
+            //    }
+            //    else
+            //    {
+            //        allGroupHeadsCollector = null;
+            //    }
+            //}
+
+            //Collector firstRound;
+            //if (allGroupHeads || allGroups)
+            //{
+            //    List<Collector> collectors = new List<Collector>();
+            //    collectors.Add(firstPassCollector);
+            //    if (allGroups)
+            //    {
+            //        collectors.Add(allGroupsCollector);
+            //    }
+            //    if (allGroupHeads)
+            //    {
+            //        collectors.Add(allGroupHeadsCollector);
+            //    }
+            //    firstRound = MultiCollector.Wrap(collectors.ToArray(/* new Collector[collectors.size()] */));
+            //}
+            //else
+            //{
+            //    firstRound = firstPassCollector;
+            //}
+
+            //CachingCollector cachedCollector = null;
+            //if (maxCacheRAMMB != null || maxDocsToCache != null)
+            //{
+            //    if (maxCacheRAMMB != null)
+            //    {
+            //        cachedCollector = CachingCollector.Create(firstRound, cacheScores, maxCacheRAMMB.Value);
+            //    }
+            //    else
+            //    {
+            //        cachedCollector = CachingCollector.Create(firstRound, cacheScores, maxDocsToCache.Value);
+            //    }
+            //    searcher.Search(query, filter, cachedCollector);
+            //}
+            //else
+            //{
+            //    searcher.Search(query, filter, firstRound);
+            //}
+
+            //if (allGroups)
+            //{
+            //    matchingGroups = (ICollection)allGroupsCollector.GetGroups();
+            //}
+            //else
+            //{
+            //    matchingGroups = (ICollection)Collections.EmptyList<TGroupValue>();
+            //}
+            //if (allGroupHeads)
+            //{
+            //    matchingGroupHeads = allGroupHeadsCollector.RetrieveGroupHeads(searcher.IndexReader.MaxDoc);
+            //}
+            //else
+            //{
+            //    matchingGroupHeads = new Bits_MatchNoBits(searcher.IndexReader.MaxDoc);
+            //}
+
+            //ICollection<SearchGroup<TGroupValue>> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
+            //if (topSearchGroups == null)
+            //{
+            //    return new TopGroups<TGroupValue>(new SortField[0], new SortField[0], 0, 0, new GroupDocs<TGroupValue>[0], float.NaN);
+            //}
+
+            //int topNInsideGroup = groupDocsOffset + groupDocsLimit;
+            //AbstractSecondPassGroupingCollector<TGroupValue> secondPassCollector;
+            //if (groupFunction != null)
+            //{
+            //    secondPassCollector = new FunctionSecondPassGroupingCollector(topSearchGroups as ICollection<SearchGroup<MutableValue>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext);
+            //}
+            //else
+            //{
+            //    secondPassCollector = new TermSecondPassGroupingCollector(groupField, topSearchGroups as ICollection<SearchGroup<BytesRef>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
+            //}
+
+            //if (cachedCollector != null && cachedCollector.Cached)
+            //{
+            //    cachedCollector.Replay(secondPassCollector);
+            //}
+            //else
+            //{
+            //    searcher.Search(query, filter, secondPassCollector);
+            //}
+
+            //if (allGroups)
+            //{
+            //    return new TopGroups<TGroupValue>(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
+            //}
+            //else
+            //{
+            //    return secondPassCollector.GetTopGroups(groupDocsOffset);
+            //}
+        }
+
+        protected TopGroups<T> GroupByDocBlock<T>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        {
+            int topN = groupOffset + groupLimit;
+            BlockGroupingCollector c = new BlockGroupingCollector(groupSort, topN, includeScores, groupEndDocs);
+            searcher.Search(query, filter, c);
+            int topNInsideGroup = groupDocsOffset + groupDocsLimit;
+            return c.GetTopGroups<T>(sortWithinGroup, groupOffset, groupDocsOffset, topNInsideGroup, fillSortFields);
+        }
+
+        /**
+         * Enables caching for the second pass search. The cache will not grow over a specified limit in MB.
+         * The cache is filled during the first pass searched and then replayed during the second pass searched.
+         * If the cache grows beyond the specified limit, then the cache is purged and not used in the second pass search.
+         *
+         * @param maxCacheRAMMB The maximum amount in MB the cache is allowed to hold
+         * @param cacheScores   Whether to cache the scores
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheScores)
+        {
+            this.maxCacheRAMMB = maxCacheRAMMB;
+            this.maxDocsToCache = null;
+            this.cacheScores = cacheScores;
+            return this;
+        }
+
+        /**
+         * Enables caching for the second pass search. The cache will not contain more than the maximum specified documents.
+         * The cache is filled during the first pass searched and then replayed during the second pass searched.
+         * If the cache grows beyond the specified limit, then the cache is purged and not used in the second pass search.
+         *
+         * @param maxDocsToCache The maximum number of documents the cache is allowed to hold
+         * @param cacheScores    Whether to cache the scores
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
+        {
+            this.maxDocsToCache = maxDocsToCache;
+            this.maxCacheRAMMB = null;
+            this.cacheScores = cacheScores;
+            return this;
+        }
+
+        /**
+         * Disables any enabled cache.
+         *
+         * @return <code>this</code>
+         */
+        public GroupingSearch DisableCaching()
+        {
+            this.maxCacheRAMMB = null;
+            this.maxDocsToCache = null;
+            return this;
+        }
+
+        /**
+         * Specifies how groups are sorted.
+         * Defaults to {@link Sort#RELEVANCE}.
+         *
+         * @param groupSort The sort for the groups.
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetGroupSort(Sort groupSort)
+        {
+            this.groupSort = groupSort;
+            return this;
+        }
+
+        /**
+         * Specified how documents inside a group are sorted.
+         * Defaults to {@link Sort#RELEVANCE}.
+         *
+         * @param sortWithinGroup The sort for documents inside a group
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
+        {
+            this.sortWithinGroup = sortWithinGroup;
+            return this;
+        }
+
+        /**
+         * Specifies the offset for documents inside a group.
+         *
+         * @param groupDocsOffset The offset for documents inside a
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetGroupDocsOffset(int groupDocsOffset)
+        {
+            this.groupDocsOffset = groupDocsOffset;
+            return this;
+        }
+
+        /**
+         * Specifies the number of documents to return inside a group from the specified groupDocsOffset.
+         *
+         * @param groupDocsLimit The number of documents to return inside a group
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetGroupDocsLimit(int groupDocsLimit)
+        {
+            this.groupDocsLimit = groupDocsLimit;
+            return this;
+        }
+
+        /**
+         * Whether to also fill the sort fields per returned group and groups docs.
+         *
+         * @param fillSortFields Whether to also fill the sort fields per returned group and groups docs
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetFillSortFields(bool fillSortFields)
+        {
+            this.fillSortFields = fillSortFields;
+            return this;
+        }
+
+        /**
+         * Whether to include the scores per doc inside a group.
+         *
+         * @param includeScores Whether to include the scores per doc inside a group
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetIncludeScores(bool includeScores)
+        {
+            this.includeScores = includeScores;
+            return this;
+        }
+
+        /**
+         * Whether to include the score of the most relevant document per group.
+         *
+         * @param includeMaxScore Whether to include the score of the most relevant document per group
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetIncludeMaxScore(bool includeMaxScore)
+        {
+            this.includeMaxScore = includeMaxScore;
+            return this;
+        }
+
+        /**
+         * Whether to also compute all groups matching the query.
+         * This can be used to determine the number of groups, which can be used for accurate pagination.
+         * <p/>
+         * When grouping by doc block the number of groups are automatically included in the {@link TopGroups} and this
+         * option doesn't have any influence.
+         *
+         * @param allGroups to also compute all groups matching the query
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetAllGroups(bool allGroups)
+        {
+            this.allGroups = allGroups;
+            return this;
+        }
+
+        /**
+         * If {@link #setAllGroups(boolean)} was set to <code>true</code> then all matching groups are returned, otherwise
+         * an empty collection is returned.
+         *
+         * @param <T> The group value type. This can be a {@link BytesRef} or a {@link MutableValue} instance. If grouping
+         *            by doc block this the group value is always <code>null</code>.
+         * @return all matching groups are returned, or an empty collection
+         */
+        public ICollection<T> GetAllMatchingGroups<T>()
+        {
+            return (ICollection<T>)matchingGroups;
+        }
+
+        /**
+         * Whether to compute all group heads (most relevant document per group) matching the query.
+         * <p/>
+         * This feature isn't enabled when grouping by doc block.
+         *
+         * @param allGroupHeads Whether to compute all group heads (most relevant document per group) matching the query
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetAllGroupHeads(bool allGroupHeads)
+        {
+            this.allGroupHeads = allGroupHeads;
+            return this;
+        }
+
+        /**
+         * Returns the matching group heads if {@link #setAllGroupHeads(boolean)} was set to true or an empty bit set.
+         *
+         * @return The matching group heads if {@link #setAllGroupHeads(boolean)} was set to true or an empty bit set
+         */
+        public Bits GetAllGroupHeads()
+        {
+            return matchingGroupHeads;
+        }
+
+        /**
+         * Sets the initial size of some internal used data structures.
+         * This prevents growing data structures many times. This can improve the performance of the grouping at the cost of
+         * more initial RAM.
+         * <p/>
+         * The {@link #setAllGroups} and {@link #setAllGroupHeads} features use this option.
+         * Defaults to 128.
+         *
+         * @param initialSize The initial size of some internal used data structures
+         * @return <code>this</code>
+         */
+        public GroupingSearch SetInitialSize(int initialSize)
+        {
+            this.initialSize = initialSize;
+            return this;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj b/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
index 5d4fbe2..b10cd40 100644
--- a/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
+++ b/src/Lucene.Net.Grouping/Lucene.Net.Grouping.csproj
@@ -40,8 +40,29 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AbstractAllGroupHeadsCollector.cs" />
+    <Compile Include="AbstractAllGroupsCollector.cs" />
+    <Compile Include="AbstractDistinctValuesCollector.cs" />
+    <Compile Include="AbstractFirstPassGroupingCollector.cs" />
+    <Compile Include="AbstractGroupFacetCollector.cs" />
+    <Compile Include="AbstractSecondPassGroupingCollector.cs" />
+    <Compile Include="BlockGroupingCollector.cs" />
+    <Compile Include="CollectedSearchGroup.cs" />
+    <Compile Include="Function\FunctionAllGroupHeadsCollector.cs" />
+    <Compile Include="Function\FunctionAllGroupsCollector.cs" />
+    <Compile Include="Function\FunctionDistinctValuesCollector.cs" />
+    <Compile Include="Function\FunctionFirstPassGroupingCollector.cs" />
+    <Compile Include="Function\FunctionSecondPassGroupingCollector.cs" />
     <Compile Include="GroupDocs.cs" />
+    <Compile Include="GroupingSearch.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="SearchGroup.cs" />
+    <Compile Include="Term\TermAllGroupHeadsCollector.cs" />
+    <Compile Include="Term\TermAllGroupsCollector.cs" />
+    <Compile Include="Term\TermDistinctValuesCollector.cs" />
+    <Compile Include="Term\TermFirstPassGroupingCollector.cs" />
+    <Compile Include="Term\TermGroupFacetCollector.cs" />
+    <Compile Include="Term\TermSecondPassGroupingCollector.cs" />
     <Compile Include="TopGroups.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -49,7 +70,12 @@
       <Project>{5D4AD9BE-1FFB-41AB-9943-25737971BF57}</Project>
       <Name>Lucene.Net</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 />
   <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.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
new file mode 100644
index 0000000..6ab902f
--- /dev/null
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -0,0 +1,388 @@
+\ufeffusing Lucene.Net.Search;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// Represents a group that is found during the first pass search.
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public class SearchGroup<TGroupValue>
+    {
+        /** The value that defines this group  */
+        public TGroupValue groupValue;
+
+        /** The sort values used during sorting. These are the
+         *  groupSort field values of the highest rank document
+         *  (by the groupSort) within the group.  Can be
+         * <code>null</code> if <code>fillFields=false</code> had
+         * been passed to {@link AbstractFirstPassGroupingCollector#getTopGroups} */
+        public object[] sortValues;
+
+        public override string ToString()
+        {
+            return ("SearchGroup(groupValue=" + groupValue + " sortValues=" + Arrays.ToString(sortValues) + ")");
+        }
+
+        public override bool Equals(object o)
+        {
+            if (this == o) return true;
+            if (o == null || GetType() != o.GetType()) return false;
+
+            SearchGroup<TGroupValue> that = (SearchGroup<TGroupValue>)o;
+
+            if (groupValue == null)
+            {
+                if (that.groupValue != null)
+                {
+                    return false;
+                }
+            }
+            else if (!groupValue.Equals(that.groupValue))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public override int GetHashCode()
+        {
+            return groupValue != null ? groupValue.GetHashCode() : 0;
+        }
+
+        private class ShardIter<T>
+        {
+            public readonly IEnumerator<SearchGroup<T>> iter;
+            public readonly int shardIndex;
+
+            public ShardIter(ICollection<SearchGroup<T>> shard, int shardIndex)
+            {
+                this.shardIndex = shardIndex;
+                iter = shard.GetEnumerator();
+                //Debug.Assert(iter.hasNext());
+            }
+
+            public SearchGroup<T> Next()
+            {
+                Debug.Assert(iter.MoveNext());
+                SearchGroup<T> group = iter.Current;
+                if (group.sortValues == null)
+                {
+                    throw new ArgumentException("group.sortValues is null; you must pass fillFields=true to the first pass collector");
+                }
+                return group;
+            }
+
+            public override string ToString()
+            {
+                return "ShardIter(shard=" + shardIndex + ")";
+            }
+        }
+
+        // Holds all shards currently on the same group
+        private class MergedGroup<T>
+        {
+
+            // groupValue may be null!
+            public readonly T groupValue;
+
+            public object[] topValues;
+            public readonly List<ShardIter<T>> shards = new List<ShardIter<T>>();
+            public int minShardIndex;
+            public bool processed;
+            public bool inQueue;
+
+            public MergedGroup(T groupValue)
+            {
+                this.groupValue = groupValue;
+            }
+
+            // Only for assert
+            private bool NeverEquals(object _other)
+            {
+                if (_other is MergedGroup<T>)
+                {
+                    MergedGroup<T> other = (MergedGroup<T>)_other;
+                    if (groupValue == null)
+                    {
+                        Debug.Assert(other.groupValue != null);
+                    }
+                    else
+                    {
+                        Debug.Assert(!groupValue.Equals(other.groupValue));
+                    }
+                }
+                return true;
+            }
+
+            public override bool Equals(object _other)
+            {
+                // We never have another MergedGroup instance with
+                // same groupValue
+                Debug.Assert(NeverEquals(_other));
+
+                if (_other is MergedGroup<T>)
+                {
+                    MergedGroup<T> other = (MergedGroup<T>)_other;
+                    if (groupValue == null)
+                    {
+                        return other == null;
+                    }
+                    else
+                    {
+                        return groupValue.Equals(other);
+                    }
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            public override int GetHashCode()
+            {
+                if (groupValue == null)
+                {
+                    return 0;
+                }
+                else
+                {
+                    return groupValue.GetHashCode();
+                }
+            }
+        }
+
+        private class GroupComparator<T> : IComparer<MergedGroup<T>>
+        {
+
+            public readonly FieldComparator[] comparators;
+            public readonly int[] reversed;
+
+            public GroupComparator(Sort groupSort)
+            {
+                SortField[] sortFields = groupSort.GetSort();
+                comparators = new FieldComparator[sortFields.Length];
+                reversed = new int[sortFields.Length];
+                for (int compIDX = 0; compIDX < sortFields.Length; compIDX++)
+                {
+                    SortField sortField = sortFields[compIDX];
+                    comparators[compIDX] = sortField.GetComparator(1, compIDX);
+                    reversed[compIDX] = sortField.Reverse ? -1 : 1;
+                }
+            }
+
+            public virtual int Compare(MergedGroup<T> group, MergedGroup<T> other)
+            {
+                if (group == other)
+                {
+                    return 0;
+                }
+                //System.out.println("compare group=" + group + " other=" + other);
+                object[] groupValues = group.topValues;
+                object[] otherValues = other.topValues;
+                //System.out.println("  groupValues=" + groupValues + " otherValues=" + otherValues);
+                for (int compIDX = 0; compIDX < comparators.Length; compIDX++)
+                {
+                    int c = reversed[compIDX] * comparators[compIDX].CompareValues(groupValues[compIDX],
+                                                                                         otherValues[compIDX]);
+                    if (c != 0)
+                    {
+                        return c;
+                    }
+                }
+
+                // Tie break by min shard index:
+                Debug.Assert(group.minShardIndex != other.minShardIndex);
+                return group.minShardIndex - other.minShardIndex;
+            }
+        }
+
+        private class GroupMerger<T>
+        {
+
+            private readonly GroupComparator<T> groupComp;
+            private readonly ISet<MergedGroup<T>> queue;
+            private readonly IDictionary<T, MergedGroup<T>> groupsSeen;
+
+            public GroupMerger(Sort groupSort)
+            {
+                groupComp = new GroupComparator<T>(groupSort);
+                queue = new SortedSet<MergedGroup<T>>(groupComp);
+                groupsSeen = new Dictionary<T, MergedGroup<T>>();
+            }
+
+            private void UpdateNextGroup(int topN, ShardIter<T> shard)
+            {
+                while (shard.iter.MoveNext())
+                {
+                    SearchGroup<T> group = shard.Next();
+                    MergedGroup<T> mergedGroup = groupsSeen.ContainsKey(group.groupValue) ? groupsSeen[group.groupValue] : null;
+                    bool isNew = mergedGroup == null;
+                    //System.out.println("    next group=" + (group.groupValue == null ? "null" : ((BytesRef) group.groupValue).utf8ToString()) + " sort=" + Arrays.toString(group.sortValues));
+
+                    if (isNew)
+                    {
+                        // Start a new group:
+                        //System.out.println("      new");
+                        mergedGroup = new MergedGroup<T>(group.groupValue);
+                        mergedGroup.minShardIndex = shard.shardIndex;
+                        Debug.Assert(group.sortValues != null);
+                        mergedGroup.topValues = group.sortValues;
+                        groupsSeen[group.groupValue] = mergedGroup;
+                        mergedGroup.inQueue = true;
+                        queue.Add(mergedGroup);
+                    }
+                    else if (mergedGroup.processed)
+                    {
+                        // This shard produced a group that we already
+                        // processed; move on to next group...
+                        continue;
+                    }
+                    else
+                    {
+                        //System.out.println("      old");
+                        bool competes = false;
+                        for (int compIDX = 0; compIDX < groupComp.comparators.Length; compIDX++)
+                        {
+                            int cmp = groupComp.reversed[compIDX] * groupComp.comparators[compIDX].CompareValues(group.sortValues[compIDX],
+                                                                                                                       mergedGroup.topValues[compIDX]);
+                            if (cmp < 0)
+                            {
+                                // Definitely competes
+                                competes = true;
+                                break;
+                            }
+                            else if (cmp > 0)
+                            {
+                                // Definitely does not compete
+                                break;
+                            }
+                            else if (compIDX == groupComp.comparators.Length - 1)
+                            {
+                                if (shard.shardIndex < mergedGroup.minShardIndex)
+                                {
+                                    competes = true;
+                                }
+                            }
+                        }
+
+                        //System.out.println("      competes=" + competes);
+
+                        if (competes)
+                        {
+                            // Group's sort changed -- remove & re-insert
+                            if (mergedGroup.inQueue)
+                            {
+                                queue.Remove(mergedGroup);
+                            }
+                            mergedGroup.topValues = group.sortValues;
+                            mergedGroup.minShardIndex = shard.shardIndex;
+                            queue.Add(mergedGroup);
+                            mergedGroup.inQueue = true;
+                        }
+                    }
+
+                    mergedGroup.shards.Add(shard);
+                    break;
+                }
+
+                // Prune un-competitive groups:
+                while (queue.Count > topN)
+                {
+                    MergedGroup<T> group = queue.Last();
+                    queue.Remove(group);
+                    //System.out.println("PRUNE: " + group);
+                    group.inQueue = false;
+                }
+            }
+
+            public ICollection<SearchGroup<T>> Merge(IList<ICollection<SearchGroup<T>>> shards, int offset, int topN)
+            {
+
+                int maxQueueSize = offset + topN;
+
+                //System.out.println("merge");
+                // Init queue:
+                for (int shardIDX = 0; shardIDX < shards.Count; shardIDX++)
+                {
+                    ICollection<SearchGroup<T>> shard = shards[shardIDX];
+                    if (shard.Any())
+                    {
+                        //System.out.println("  insert shard=" + shardIDX);
+                        UpdateNextGroup(maxQueueSize, new ShardIter<T>(shard, shardIDX));
+                    }
+                }
+
+                // Pull merged topN groups:
+                List<SearchGroup<T>> newTopGroups = new List<SearchGroup<T>>();
+
+                int count = 0;
+
+                while (queue.Count != 0)
+                {
+                    MergedGroup<T> group = queue.First();
+                    queue.Remove(group);
+                    group.processed = true;
+                    //System.out.println("  pop: shards=" + group.shards + " group=" + (group.groupValue == null ? "null" : (((BytesRef) group.groupValue).utf8ToString())) + " sortValues=" + Arrays.toString(group.topValues));
+                    if (count++ >= offset)
+                    {
+                        SearchGroup<T> newGroup = new SearchGroup<T>();
+                        newGroup.groupValue = group.groupValue;
+                        newGroup.sortValues = group.topValues;
+                        newTopGroups.Add(newGroup);
+                        if (newTopGroups.Count == topN)
+                        {
+                            break;
+                        }
+                        //} else {
+                        // System.out.println("    skip < offset");
+                    }
+
+                    // Advance all iters in this group:
+                    foreach (ShardIter<T> shardIter in group.shards)
+                    {
+                        UpdateNextGroup(maxQueueSize, shardIter);
+                    }
+                }
+
+                if (newTopGroups.Count == 0)
+                {
+                    return null;
+                }
+                else
+                {
+                    return newTopGroups;
+                }
+            }
+        }
+
+        /** Merges multiple collections of top groups, for example
+         *  obtained from separate index shards.  The provided
+         *  groupSort must match how the groups were sorted, and
+         *  the provided SearchGroups must have been computed
+         *  with fillFields=true passed to {@link
+         *  AbstractFirstPassGroupingCollector#getTopGroups}.
+         *
+         * <p>NOTE: this returns null if the topGroups is empty.
+         */
+        public static ICollection<SearchGroup<T>> Merge<T>(IList<ICollection<SearchGroup<T>>> topGroups, int offset, int topN, Sort groupSort)
+        {
+            if (topGroups.Count == 0)
+            {
+                return null;
+            }
+            else
+            {
+                return new GroupMerger<T>(groupSort).Merge(topGroups, offset, topN);
+            }
+        }
+    }
+}


[27/58] [abbrv] lucenenet git commit: Added TODO to rename the Core.Search.CachingCollector.Cached property to IsCached.

Posted by ni...@apache.org.
Added TODO to rename the Core.Search.CachingCollector.Cached property to IsCached.


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

Branch: refs/heads/grouping
Commit: 8cc1a3f443d1715919f61134cdf771b05c9500ef
Parents: a209d71
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Wed Nov 2 23:06:08 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:52 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Search/CachingCollector.cs | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8cc1a3f4/src/Lucene.Net.Core/Search/CachingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Search/CachingCollector.cs b/src/Lucene.Net.Core/Search/CachingCollector.cs
index 4c41dab..a0573ac 100644
--- a/src/Lucene.Net.Core/Search/CachingCollector.cs
+++ b/src/Lucene.Net.Core/Search/CachingCollector.cs
@@ -484,6 +484,7 @@ namespace Lucene.Net.Search
             return Other.AcceptsDocsOutOfOrder();
         }
 
+        // LUCENENET TODO: Rename to IsCached
         public virtual bool Cached
         {
             get


[15/58] [abbrv] lucenenet git commit: Added Core.Support.LinkedHashMap + tests for supporting guaranteed insertion order enumeration of an IDictionary structure.

Posted by ni...@apache.org.
Added Core.Support.LinkedHashMap + tests for supporting guaranteed insertion order enumeration of an IDictionary structure.


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

Branch: refs/heads/grouping
Commit: 7723e26d74297b714fa3b67cef940f6072322296
Parents: 63fa4ca
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 19:52:23 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Mon Nov 7 18:44:14 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Lucene.Net.csproj           |   1 +
 src/Lucene.Net.Core/Support/HashMap.cs          |  49 +-
 src/Lucene.Net.Core/Support/LinkedHashMap.cs    | 523 +++++++++++++++++++
 src/Lucene.Net.Tests/Lucene.Net.Tests.csproj    |   1 +
 .../core/Support/TestLinkedHashMap.cs           | 359 +++++++++++++
 5 files changed, 916 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7723e26d/src/Lucene.Net.Core/Lucene.Net.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Lucene.Net.csproj b/src/Lucene.Net.Core/Lucene.Net.csproj
index 09915fb..5ce5f82 100644
--- a/src/Lucene.Net.Core/Lucene.Net.csproj
+++ b/src/Lucene.Net.Core/Lucene.Net.csproj
@@ -643,6 +643,7 @@
     <Compile Include="Support\IdentityWeakReference.cs" />
     <Compile Include="Support\IDictionaryExtensions.cs" />
     <Compile Include="Support\LimitedConcurrencyLevelTaskScheduler.cs" />
+    <Compile Include="Support\LinkedHashMap.cs" />
     <Compile Include="Support\ListExtensions.cs" />
     <Compile Include="Support\LongBuffer.cs" />
     <Compile Include="Support\LurchTable.cs" />

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7723e26d/src/Lucene.Net.Core/Support/HashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/HashMap.cs b/src/Lucene.Net.Core/Support/HashMap.cs
index 0fcf29a..ce3831d 100644
--- a/src/Lucene.Net.Core/Support/HashMap.cs
+++ b/src/Lucene.Net.Core/Support/HashMap.cs
@@ -22,6 +22,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Text;
 
 namespace Lucene.Net.Support
 {
@@ -52,6 +53,20 @@ namespace Lucene.Net.Support
     /// </summary>
     /// <typeparam name="TKey">The type of keys in the dictionary</typeparam>
     /// <typeparam name="TValue">The type of values in the dictionary</typeparam>
+    /// <remarks>
+    /// <h2>Unordered Dictionaries</h2>
+    /// <list type="bullet">
+    ///     <item><see cref="Dictionary{TKey, TValue}"/> - use when order is not important and all keys are non-null.</item>
+    ///     <item><see cref="HashMap{TKey, TValue}"/> - use when order is not important and support for a null key is required.</item>
+    /// </list>
+    /// <h2>Ordered Dictionaries</h2>
+    /// <list type="bullet">
+    ///     <item><see cref="LinkedHashMap{TKey, TValue}"/> - use when you need to preserve entry insertion order. Keys are nullable.</item>
+    ///     <item><see cref="SortedDictionary{TKey, TValue}"/> - use when you need natural sort order. Keys must be unique.</item>
+    ///     <item><see cref="TreeDictionary{K, V}"/> - use when you need natural sort order. Keys may contain duplicates.</item>
+    ///     <item><see cref="LurchTable{TKey, TValue}"/> - use when you need to sort by most recent access or most recent update. Works well for LRU caching.</item>
+    /// </list>
+    /// </remarks>
     [Serializable]
     public class HashMap<TKey, TValue> : IDictionary<TKey, TValue>
     {
@@ -205,7 +220,7 @@ namespace Lucene.Net.Support
 
         #region Implementation of IEnumerable
 
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
         {
             if (!_isValueType && _hasNullValue)
             {
@@ -226,38 +241,38 @@ namespace Lucene.Net.Support
 
         #region Implementation of ICollection<KeyValuePair<TKey,TValue>>
 
-        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
+        public virtual void Add(KeyValuePair<TKey, TValue> item)
         {
             Add(item.Key, item.Value);
         }
 
-        public void Clear()
+        public virtual void Clear()
         {
             _hasNullValue = false;
             _nullValue = default(TValue);
             _dict.Clear();
         }
 
-        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+        public virtual bool Contains(KeyValuePair<TKey, TValue> item)
         {
             if (!_isValueType && _comparer.Equals(item.Key, default(TKey)))
             {
                 return _hasNullValue && EqualityComparer<TValue>.Default.Equals(item.Value, _nullValue);
             }
 
-            return ((ICollection<KeyValuePair<TKey, TValue>>)_dict).Contains(item);
+            return _dict.Contains(item);
         }
 
-        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        public virtual void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
         {
-            ((ICollection<KeyValuePair<TKey, TValue>>)_dict).CopyTo(array, arrayIndex);
+            _dict.CopyTo(array, arrayIndex);
             if (!_isValueType && _hasNullValue)
             {
                 array[array.Length - 1] = new KeyValuePair<TKey, TValue>(default(TKey), _nullValue);
             }
         }
 
-        public bool Remove(KeyValuePair<TKey, TValue> item)
+        public virtual bool Remove(KeyValuePair<TKey, TValue> item)
         {
             if (!_isValueType && _comparer.Equals(item.Key, default(TKey)))
             {
@@ -269,15 +284,15 @@ namespace Lucene.Net.Support
                 return true;
             }
 
-            return ((ICollection<KeyValuePair<TKey, TValue>>)_dict).Remove(item);
+            return _dict.Remove(item);
         }
 
-        public int Count
+        public virtual int Count
         {
             get { return _dict.Count + (_hasNullValue ? 1 : 0); }
         }
 
-        public bool IsReadOnly
+        public virtual bool IsReadOnly
         {
             get { return false; }
         }
@@ -286,7 +301,7 @@ namespace Lucene.Net.Support
 
         #region Implementation of IDictionary<TKey,TValue>
 
-        public bool ContainsKey(TKey key)
+        public virtual bool ContainsKey(TKey key)
         {
             if (!_isValueType && _comparer.Equals(key, default(TKey)))
             {
@@ -313,7 +328,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        public bool Remove(TKey key)
+        public virtual bool Remove(TKey key)
         {
             if (!_isValueType && _comparer.Equals(key, default(TKey)))
             {
@@ -327,7 +342,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        public bool TryGetValue(TKey key, out TValue value)
+        public virtual bool TryGetValue(TKey key, out TValue value)
         {
             if (!_isValueType && _comparer.Equals(key, default(TKey)))
             {
@@ -346,7 +361,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        public TValue this[TKey key]
+        public virtual TValue this[TKey key]
         {
             get
             {
@@ -363,7 +378,7 @@ namespace Lucene.Net.Support
             set { Add(key, value); }
         }
 
-        public ICollection<TKey> Keys
+        public virtual ICollection<TKey> Keys
         {
             get
             {
@@ -376,7 +391,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        public ICollection<TValue> Values
+        public virtual ICollection<TValue> Values
         {
             get
             {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7723e26d/src/Lucene.Net.Core/Support/LinkedHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/LinkedHashMap.cs b/src/Lucene.Net.Core/Support/LinkedHashMap.cs
new file mode 100644
index 0000000..5ae23ce
--- /dev/null
+++ b/src/Lucene.Net.Core/Support/LinkedHashMap.cs
@@ -0,0 +1,523 @@
+\ufeffusing System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Support
+{
+    /*
+    The MIT License (MIT)
+
+    Copyright (c) 2014 matarillo
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+    */
+
+    // Source: http://qiita.com/matarillo/items/c09e0f3e5a61f84a51e2
+    // 2016-11-05 - Shad Storhaug
+    // Modified from its original form to be backed by a 
+    // HashMap rather than a Dictionary so it will support null keys.
+    // 2016-11-05 - Shad Storhaug
+    // Added KeyCollection and ValueCollection classes to prevent having to do
+    // an O(n) operation when calling the Keys or Values properties.
+
+    /// <summary>
+    /// LinkedHashMap is a specialized dictionary that preserves the entry order of elements.
+    /// Like a HashMap, there can be a <c>null</c> key, but it also guarantees that the enumeration
+    /// order of the elements are the same as insertion order, regardless of the number of add/remove/update
+    /// operations that are performed on it.
+    /// </summary>
+    /// <typeparam name="TKey">The type of keys in the dictionary</typeparam>
+    /// <typeparam name="TValue">The type of values in the dictionary</typeparam>
+    /// <remarks>
+    /// <h2>Unordered Dictionaries</h2>
+    /// <list type="bullet">
+    ///     <item><see cref="Dictionary{TKey, TValue}"/> - use when order is not important and all keys are non-null.</item>
+    ///     <item><see cref="HashMap{TKey, TValue}"/> - use when order is not important and support for a null key is required.</item>
+    /// </list>
+    /// <h2>Ordered Dictionaries</h2>
+    /// <list type="bullet">
+    ///     <item><see cref="LinkedHashMap{TKey, TValue}"/> - use when you need to preserve entry insertion order. Keys are nullable.</item>
+    ///     <item><see cref="SortedDictionary{TKey, TValue}"/> - use when you need natural sort order. Keys must be unique.</item>
+    ///     <item><see cref="TreeDictionary{K, V}"/> - use when you need natural sort order. Keys may contain duplicates.</item>
+    ///     <item><see cref="LurchTable{TKey, TValue}"/> - use when you need to sort by most recent access or most recent update. Works well for LRU caching.</item>
+    /// </list>
+    /// </remarks>
+    public class LinkedHashMap<TKey, TValue> : HashMap<TKey, TValue>, IDictionary<TKey, TValue>
+    {
+        private readonly HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> dict;
+        private readonly LinkedList<KeyValuePair<TKey, TValue>> list;
+
+        #region Constructors
+
+        public LinkedHashMap()
+        {
+            dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>();
+            list = new LinkedList<KeyValuePair<TKey, TValue>>();
+        }
+
+        public LinkedHashMap(IEqualityComparer<TKey> comparer)
+        {
+            dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(comparer);
+            list = new LinkedList<KeyValuePair<TKey, TValue>>();
+        }
+
+        public LinkedHashMap(int capacity)
+        {
+            dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(capacity);
+            list = new LinkedList<KeyValuePair<TKey, TValue>>();
+        }
+
+        public LinkedHashMap(int capacity, IEqualityComparer<TKey> comparer)
+        {
+            dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(capacity, comparer);
+            list = new LinkedList<KeyValuePair<TKey, TValue>>();
+        }
+
+        public LinkedHashMap(IEnumerable<KeyValuePair<TKey, TValue>> source)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException("source");
+            }
+            var countable = source as ICollection;
+            if (countable != null)
+            {
+                dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(countable.Count);
+            }
+            else
+            {
+                dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>();
+            }
+            list = new LinkedList<KeyValuePair<TKey, TValue>>();
+            foreach (var pair in source)
+            {
+                this[pair.Key] = pair.Value;
+            }
+        }
+
+        public LinkedHashMap(IEnumerable<KeyValuePair<TKey, TValue>> source, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException("source");
+            }
+            var countable = source as ICollection;
+            if (countable != null)
+            {
+                dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(countable.Count, comparer);
+            }
+            else
+            {
+                dict = new HashMap<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(comparer);
+            }
+            list = new LinkedList<KeyValuePair<TKey, TValue>>();
+            foreach (var pair in source)
+            {
+                this[pair.Key] = pair.Value;
+            }
+        }
+
+        #endregion
+
+        #region IEnumerable implementation
+
+        public override IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            return list.GetEnumerator();
+        }
+
+        #endregion
+
+        #region IDictionary implementation
+
+        public override bool ContainsKey(TKey key)
+        {
+            return dict.ContainsKey(key);
+        }
+
+        public override void Add(TKey key, TValue value)
+        {
+            DoAdd(key, value);
+        }
+
+        private void DoAdd(TKey key, TValue value)
+        {
+            var pair = new KeyValuePair<TKey, TValue>(key, value);
+            var node = new LinkedListNode<KeyValuePair<TKey, TValue>>(pair);
+            dict.Add(key, node);
+            list.AddLast(node);
+        }
+
+        public override bool Remove(TKey key)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> n;
+            if (!dict.TryGetValue(key, out n))
+            {
+                return false;
+            }
+            DoRemove(n);
+            return true;
+        }
+
+        private void DoRemove(LinkedListNode<KeyValuePair<TKey, TValue>> node)
+        {
+            dict.Remove(node.Value.Key);
+            list.Remove(node);
+        }
+
+        public override bool TryGetValue(TKey key, out TValue value)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> n;
+            if (dict.TryGetValue(key, out n))
+            {
+                value = n.Value.Value;
+                return true;
+            }
+            value = default(TValue);
+            return false;
+        }
+
+        private bool TryGetNode(TKey key, TValue value, out LinkedListNode<KeyValuePair<TKey, TValue>> node)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> n;
+            if (dict.TryGetValue(key, out n) && EqualityComparer<TValue>.Default.Equals(value, n.Value.Value))
+            {
+                node = n;
+                return true;
+            }
+            node = null;
+            return false;
+        }
+
+        public override TValue this[TKey key]
+        {
+            get
+            {
+                var node = dict[key];
+                if (node == null)
+                    return default(TValue);
+
+                return node.Value.Value;
+            }
+            set
+            {
+                LinkedListNode<KeyValuePair<TKey, TValue>> n;
+                if (!dict.TryGetValue(key, out n))
+                {
+                    DoAdd(key, value);
+                    return;
+                }
+                DoSet(n, key, value);
+            }
+        }
+
+        private void DoSet(LinkedListNode<KeyValuePair<TKey, TValue>> node, TKey key, TValue value)
+        {
+            var pair = new KeyValuePair<TKey, TValue>(key, value);
+            var newNode = new LinkedListNode<KeyValuePair<TKey, TValue>>(pair);
+            dict[key] = newNode;
+            list.AddAfter(node, newNode);
+            list.Remove(node);
+        }
+
+        public override ICollection<TKey> Keys
+        {
+            get
+            {
+                return new KeyCollection(this);
+            }
+        }
+
+        public override ICollection<TValue> Values
+        {
+            get
+            {
+                return new ValueCollection(this);
+            }
+        }
+
+        #endregion
+
+        #region ICollection implementation
+
+        public override void Clear()
+        {
+            dict.Clear();
+            list.Clear();
+        }
+
+        public override int Count
+        {
+            get { return dict.Count; }
+        }
+
+        public override bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        public override void Add(KeyValuePair<TKey, TValue> item)
+        {
+            Add(item.Key, item.Value);
+        }
+
+        public override bool Contains(KeyValuePair<TKey, TValue> item)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> pair;
+            return TryGetNode(item.Key, item.Value, out pair);
+        }
+
+        public override void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            list.CopyTo(array, arrayIndex);
+        }
+
+        public override bool Remove(KeyValuePair<TKey, TValue> item)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (!TryGetNode(item.Key, item.Value, out node))
+            {
+                return false;
+            }
+            DoRemove(node);
+            return true;
+        }
+
+        #endregion
+
+        #region KeyCollection
+
+        internal class KeyCollection : ICollection<TKey>
+        {
+            private readonly LinkedHashMap<TKey, TValue> outerInstance;
+
+            public KeyCollection(LinkedHashMap<TKey, TValue> outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public int Count
+            {
+                get
+                {
+                    return outerInstance.Count;
+                }
+            }
+
+            public bool IsReadOnly
+            {
+                get
+                {
+                    return false;
+                }
+            }
+
+            public void Add(TKey item)
+            {
+                throw new NotSupportedException();
+            }
+
+            public void Clear()
+            {
+                outerInstance.Clear();
+            }
+
+            public bool Contains(TKey item)
+            {
+                return outerInstance.ContainsKey(item);
+            }
+
+            public void CopyTo(TKey[] array, int arrayIndex)
+            {
+                throw new NotImplementedException("Implement this as needed");
+            }
+
+            public IEnumerator<TKey> GetEnumerator()
+            {
+                return new KeyEnumerator(outerInstance.list.GetEnumerator());
+            }
+
+            public bool Remove(TKey item)
+            {
+                return outerInstance.Remove(item);
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
+            }
+
+            #region KeyEnumerator
+
+            internal class KeyEnumerator : IEnumerator<TKey>
+            {
+                private readonly IEnumerator<KeyValuePair<TKey, TValue>> innerEnumerator;
+
+                public KeyEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> innerEnumerator)
+                {
+                    this.innerEnumerator = innerEnumerator;
+                }
+
+                public TKey Current
+                {
+                    get
+                    {
+                        return innerEnumerator.Current.Key;
+                    }
+                }
+
+                object IEnumerator.Current
+                {
+                    get
+                    {
+                        return Current;
+                    }
+                }
+
+                public void Dispose()
+                {
+                    innerEnumerator.Dispose();
+                }
+
+                public bool MoveNext()
+                {
+                    return innerEnumerator.MoveNext();
+                }
+
+                public void Reset()
+                {
+                    innerEnumerator.Reset();
+                }
+            }
+
+            #endregion
+        }
+
+        #endregion
+
+        #region ValueCollection
+
+        internal class ValueCollection : ICollection<TValue>
+        {
+            private readonly LinkedHashMap<TKey, TValue> outerInstance;
+
+            public ValueCollection(LinkedHashMap<TKey, TValue> outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public int Count
+            {
+                get
+                {
+                    return outerInstance.Count;
+                }
+            }
+
+            public bool IsReadOnly
+            {
+                get
+                {
+                    return false;
+                }
+            }
+
+            public void Add(TValue item)
+            {
+                throw new NotSupportedException();
+            }
+
+            public void Clear()
+            {
+                outerInstance.Clear();
+            }
+
+            public bool Contains(TValue item)
+            {
+                return outerInstance.ContainsValue(item);
+            }
+
+            public void CopyTo(TValue[] array, int arrayIndex)
+            {
+                throw new NotImplementedException("Implement this as needed");
+            }
+
+            public IEnumerator<TValue> GetEnumerator()
+            {
+                return new ValueEnumerator(outerInstance.list.GetEnumerator());
+            }
+
+            public bool Remove(TValue item)
+            {
+                throw new NotSupportedException();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
+            }
+
+
+            internal class ValueEnumerator : IEnumerator<TValue>
+            {
+                private readonly IEnumerator<KeyValuePair<TKey, TValue>> innerEnumerator;
+
+                public ValueEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> innerEnumerator)
+                {
+                    this.innerEnumerator = innerEnumerator;
+                }
+
+                public TValue Current
+                {
+                    get
+                    {
+                        return innerEnumerator.Current.Value;
+                    }
+                }
+
+                object IEnumerator.Current
+                {
+                    get
+                    {
+                        return Current;
+                    }
+                }
+
+                public void Dispose()
+                {
+                    innerEnumerator.Dispose();
+                }
+
+                public bool MoveNext()
+                {
+                    return innerEnumerator.MoveNext();
+                }
+
+                public void Reset()
+                {
+                    innerEnumerator.Reset();
+                }
+            }
+        }
+
+        
+
+        #endregion
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7723e26d/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 0b0ad11..9e6377e 100644
--- a/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
+++ b/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
@@ -484,6 +484,7 @@
     <Compile Include="core\Support\C5\WeakViewList.cs" />
     <Compile Include="core\Support\C5\Wrappers.cs" />
     <Compile Include="core\Support\TestHashMap.cs" />
+    <Compile Include="core\Support\TestLinkedHashMap.cs" />
     <Compile Include="core\Support\TestLongBuffer.cs" />
     <Compile Include="core\Support\TestByteBuffer.cs" />
     <Compile Include="core\Support\TestLurchTable.cs" />

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7723e26d/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs b/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
new file mode 100644
index 0000000..73875e2
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
@@ -0,0 +1,359 @@
+\ufeffusing Lucene.Net.Attributes;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Support
+{
+    /*
+     * 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 TestLinkedHashMap : TestHashMap
+    {
+        protected override HashMap<TKey, TValue> GetNewHashMap<TKey, TValue>()
+        {
+            return new LinkedHashMap<TKey, TValue>();
+        }
+
+        private IDictionary<FakeKey<int>, string> GetDefaultHashMap2()
+        {
+            var dict = GetNewHashMap<FakeKey<int>, string>();
+
+            dict[new FakeKey<int>(2)] = "MyString";
+            dict[new FakeKey<int>(0)] = "OtherString";
+            dict[new FakeKey<int>(5)] = "NumberFive";
+            dict[new FakeKey<int>(int.MaxValue)] = "Maximum";
+            dict[null] = "NullValue";
+            dict[new FakeKey<int>(int.MinValue)] = "Minimum";
+
+            return dict;
+        }
+
+        internal class FakeKey<T>
+        {
+            private readonly T key;
+
+            public FakeKey(T key)
+            {
+                this.key = key;
+            }
+
+            public override bool Equals(object obj)
+            {
+                // NOTE: This takes into consideration that value
+                // types cannot be null.
+                if (key == null && obj == null)
+                {
+                    return true;
+                }
+
+                if (!(obj is FakeKey<T>))
+                {
+                    return false;
+                }
+
+                return key.Equals(((FakeKey<T>)obj).key);
+            }
+
+            public override int GetHashCode()
+            {
+                // NOTE: This takes into consideration that value
+                // types cannot be null.
+                if (key == null)
+                {
+                    return 0; // Emulates Objects.hashcode(object) in Java
+                }
+
+                return key.GetHashCode();
+            }
+
+            public override string ToString()
+            {
+                // NOTE: This takes into consideration that value
+                // types cannot be null.
+                if (key == null)
+                {
+                    return "null"; // Emulates String.valueOf(object) in Java
+                }
+
+                return key.ToString();
+            }
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestInsertionOrderNullFirst()
+        {
+            var dict = GetNewHashMap<FakeKey<int>, string>();
+
+            dict[null] = "NullValue";
+            dict[new FakeKey<int>(2)] = "MyString";
+            dict[new FakeKey<int>(0)] = "OtherString";
+            dict[new FakeKey<int>(5)] = "NumberFive";
+            dict[new FakeKey<int>(int.MaxValue)] = "Maximum";
+
+            var expectedOrder = new List<KeyValuePair<FakeKey<int>, string>>
+            {
+                new KeyValuePair<FakeKey<int>, string>(null, "NullValue"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(2), "MyString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(0), "OtherString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(5), "NumberFive"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MaxValue), "Maximum"),
+            };
+
+            AssertEnumerationOrder(expectedOrder, dict);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestInsertionOrderNullInMiddle()
+        {
+            var dict = GetNewHashMap<FakeKey<int>, string>();
+
+            dict[new FakeKey<int>(2)] = "MyString";
+            dict[new FakeKey<int>(0)] = "OtherString";
+            dict[null] = "NullValue";
+            dict[new FakeKey<int>(5)] = "NumberFive";
+            dict[new FakeKey<int>(int.MaxValue)] = "Maximum";
+
+            var expectedOrder = new List<KeyValuePair<FakeKey<int>, string>>
+            {
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(2), "MyString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(0), "OtherString"),
+                new KeyValuePair<FakeKey<int>, string>(null, "NullValue"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(5), "NumberFive"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MaxValue), "Maximum"),
+            };
+
+            AssertEnumerationOrder(expectedOrder, dict);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestInsertionOrderNullLast()
+        {
+            var dict = GetNewHashMap<FakeKey<int>, string>();
+
+            dict[new FakeKey<int>(2)] = "MyString";
+            dict[new FakeKey<int>(0)] = "OtherString";
+            dict[new FakeKey<int>(5)] = "NumberFive";
+            dict[new FakeKey<int>(int.MaxValue)] = "Maximum";
+            dict[null] = "NullValue";
+
+            var expectedOrder = new List<KeyValuePair<FakeKey<int>, string>>
+            {
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(2), "MyString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(0), "OtherString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(5), "NumberFive"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MaxValue), "Maximum"),
+                new KeyValuePair<FakeKey<int>, string>(null, "NullValue"),
+            };
+
+            AssertEnumerationOrder(expectedOrder, dict);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestInsertionOrderNullAfterRemovingElements()
+        {
+            var dict = GetDefaultHashMap2();
+
+            // Remove elements before the null value to make sure
+            // we track the proper position of the null
+            dict.Remove(new FakeKey<int>(5));
+            dict.Remove(new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(0), "OtherString"));
+
+            var expectedOrder = new List<KeyValuePair<FakeKey<int>, string>>
+            {
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(2), "MyString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MaxValue), "Maximum"),
+                new KeyValuePair<FakeKey<int>, string>(null, "NullValue"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MinValue), "Minimum"),
+            };
+
+            AssertEnumerationOrder(expectedOrder, dict);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void TestInsertionOrderNullAfterRefillingBuckets()
+        {
+            var dict = GetDefaultHashMap2();
+
+            // Remove elements before the null value to make sure
+            // we track the proper position of the null
+            dict.Remove(new FakeKey<int>(5));
+            dict.Remove(new FakeKey<int>(0));
+
+            // This has been verified that it puts the reused key before "new FakeKey<int>(int.MaxValue)"
+            // in a standard Dictionary (putting it out of insertion order)
+            dict.Add(new FakeKey<int>(5), "Testing");
+
+            var expectedOrder = new List<KeyValuePair<FakeKey<int>, string>>
+            {
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(2), "MyString"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MaxValue), "Maximum"),
+                new KeyValuePair<FakeKey<int>, string>(null, "NullValue"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(int.MinValue), "Minimum"),
+                new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(5), "Testing"),
+            };
+
+            AssertEnumerationOrder(expectedOrder, dict);
+        }
+
+        private void AssertEnumerationOrder<TKey, TValue>(IList<KeyValuePair<TKey, TValue>> expectedOrder, IDictionary<TKey, TValue> actualOrder)
+        {
+            // check element order
+            int expectedCount = expectedOrder.Count;
+            var elementEnumerator = actualOrder.GetEnumerator();
+            for (int i = 0; i < expectedCount; i++)
+            {
+                Assert.IsTrue(elementEnumerator.MoveNext());
+                Assert.AreEqual(expectedOrder[i].Key, elementEnumerator.Current.Key);
+                Assert.AreEqual(expectedOrder[i].Value, elementEnumerator.Current.Value);
+            }
+
+            Assert.IsFalse(elementEnumerator.MoveNext());
+            Assert.IsFalse(elementEnumerator.MoveNext());
+
+            // check key order
+            var keyEnumerator = actualOrder.Keys.GetEnumerator();
+            for (int i = 0; i < expectedCount; i++)
+            {
+                Assert.IsTrue(keyEnumerator.MoveNext());
+                Assert.AreEqual(expectedOrder[i].Key, keyEnumerator.Current);
+            }
+
+            Assert.IsFalse(keyEnumerator.MoveNext());
+            Assert.IsFalse(keyEnumerator.MoveNext());
+
+            // check value order
+            var valueEnumerator = actualOrder.Values.GetEnumerator();
+            for (int i = 0; i < expectedCount; i++)
+            {
+                Assert.IsTrue(valueEnumerator.MoveNext());
+                Assert.AreEqual(expectedOrder[i].Value, valueEnumerator.Current);
+            }
+
+            Assert.IsFalse(valueEnumerator.MoveNext());
+            Assert.IsFalse(valueEnumerator.MoveNext());
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void TestCopyTo()
+        {
+            var dict = GetDefaultHashMap2();
+
+            KeyValuePair<FakeKey<int>, string>[] elements = new KeyValuePair<FakeKey<int>, string>[dict.Count];
+
+            dict.CopyTo(elements, 0);
+
+            // element insertion order
+            var enumerator = elements.GetEnumerator();
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(2), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("MyString", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(0), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("OtherString", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(5), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("NumberFive", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(int.MaxValue), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("Maximum", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(null, ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("NullValue", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(int.MinValue), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("Minimum", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsFalse(enumerator.MoveNext());
+            Assert.IsFalse(enumerator.MoveNext());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCopyToWithOffset()
+        {
+            int offset = 5;
+            var dict = GetDefaultHashMap2();
+
+            KeyValuePair<FakeKey<int>, string>[] elements = new KeyValuePair<FakeKey<int>, string>[dict.Count + offset];
+
+            dict.CopyTo(elements, offset);
+
+            // element insertion order
+            var enumerator = elements.GetEnumerator();
+
+            for (int i = 0; i < offset; i++)
+            {
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual(null, ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+                Assert.AreEqual(null, ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+            }
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(2), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("MyString", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(0), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("OtherString", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(5), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("NumberFive", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(int.MaxValue), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("Maximum", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(null, ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("NullValue", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual(new FakeKey<int>(int.MinValue), ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Key);
+            Assert.AreEqual("Minimum", ((KeyValuePair<FakeKey<int>, string>)enumerator.Current).Value);
+
+            Assert.IsFalse(enumerator.MoveNext());
+            Assert.IsFalse(enumerator.MoveNext());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestContainsKeyValuePair()
+        {
+            var dict = GetDefaultHashMap2();
+
+            var realTarget = new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(5), "NumberFive");
+            Assert.IsTrue(dict.Contains(realTarget));
+
+            var nullTarget = new KeyValuePair<FakeKey<int>, string>(null, "NullValue");
+            Assert.IsTrue(dict.Contains(nullTarget));
+
+            var invalidTarget = new KeyValuePair<FakeKey<int>, string>(new FakeKey<int>(543), "NullValue");
+            Assert.IsFalse(dict.Contains(invalidTarget));
+
+            dict.Remove(nullTarget);
+            Assert.IsFalse(dict.Contains(nullTarget));
+        }
+    }
+}


[09/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Core/Support/TreeDictionary.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/TreeDictionary.cs b/src/Lucene.Net.Core/Support/TreeDictionary.cs
new file mode 100644
index 0000000..c79c848
--- /dev/null
+++ b/src/Lucene.Net.Core/Support/TreeDictionary.cs
@@ -0,0 +1,74 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using Lucene.Net.Support.C5;
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support
+{
+    /// <summary>
+    /// A sorted generic dictionary based on a red-black tree set.
+    /// </summary>
+    [Serializable]
+    public class TreeDictionary<K, V> : SortedDictionaryBase<K, V>, IDictionary<K, V>, ISortedDictionary<K, V>
+    {
+
+        #region Constructors
+
+        /// <summary>
+        /// Create a red-black tree dictionary using the natural comparer for keys.
+        /// <exception cref="ArgumentException"/> if the key type K is not comparable.
+        /// </summary>
+		public TreeDictionary(MemoryType memoryType = MemoryType.Normal) : this(SCG.Comparer<K>.Default, EqualityComparer<K>.Default, memoryType) { }
+
+        /// <summary>
+        /// Create a red-black tree dictionary using an external comparer for keys.
+        /// </summary>
+        /// <param name="comparer">The external comparer</param>
+		/// <param name = "memoryType"></param>
+		public TreeDictionary(SCG.IComparer<K> comparer, MemoryType memoryType = MemoryType.Normal) : this(comparer, new ComparerZeroHashCodeEqualityComparer<K>(comparer)) { }
+
+        TreeDictionary(SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(comparer, equalityComparer, memoryType)
+        {
+            pairs = sortedpairs = new TreeSet<KeyValuePair<K, V>>(new KeyValuePairComparer<K, V>(comparer));
+            if (memoryType != MemoryType.Normal)
+                throw new Exception("TreeDictionary doesn't support MemoryType Strict or Safe");
+
+        }
+
+        #endregion
+
+        //TODO: put in interface
+        /// <summary>
+        /// Make a snapshot of the current state of this dictionary
+        /// </summary>
+        /// <returns>The snapshot</returns>
+        public SCG.IEnumerable<KeyValuePair<K, V>> Snapshot()
+        {
+            TreeDictionary<K, V> res = (TreeDictionary<K, V>)MemberwiseClone();
+
+            res.pairs = (TreeSet<KeyValuePair<K, V>>)((TreeSet<KeyValuePair<K, V>>)sortedpairs).Snapshot();
+            return res;
+        }
+    }
+}
\ No newline at end of file


[40/58] [abbrv] lucenenet git commit: Added interfaces to GroupDocs, SearchGroup, and TopGroups to apply covariance so they act more like the wildcard generics that were used in Java.

Posted by ni...@apache.org.
Added interfaces to GroupDocs, SearchGroup, and TopGroups to apply covariance so they act more like the wildcard generics that were used in Java.


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

Branch: refs/heads/grouping
Commit: 0a137bea5285ac0022861b67339665ace2ae9f49
Parents: a8f7f42
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Wed Nov 2 20:37:20 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:55 2016 +0700

----------------------------------------------------------------------
 .../AbstractAllGroupHeadsCollector.cs           |  42 +--
 .../AbstractAllGroupsCollector.cs               |  65 +++--
 .../AbstractFirstPassGroupingCollector.cs       |  41 ++-
 .../AbstractSecondPassGroupingCollector.cs      |  25 +-
 .../Function/FunctionAllGroupsCollector.cs      |   2 +-
 .../Function/FunctionDistinctValuesCollector.cs |   2 +-
 src/Lucene.Net.Grouping/GroupDocs.cs            |  57 +++-
 src/Lucene.Net.Grouping/GroupingSearch.cs       | 286 ++++++++++---------
 src/Lucene.Net.Grouping/SearchGroup.cs          |  47 +--
 .../Term/TermAllGroupsCollector.cs              |   2 +-
 .../Term/TermDistinctValuesCollector.cs         |   2 +-
 src/Lucene.Net.Grouping/TopGroups.cs            |  62 +++-
 12 files changed, 392 insertions(+), 241 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
index a3ae1bf..f27d2e4 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -224,22 +224,28 @@ namespace Lucene.Net.Search.Grouping
         protected abstract void RetrieveGroupHeadAndAddIfNotExist(int doc);
     }
 
-    /////// <summary>
-    /////// LUCENENET specific interface used to reference an 
-    /////// <see cref="AbstractAllGroupHeadsCollector{GH}"/> subclass
-    /////// without refering to its generic closing type.
-    /////// </summary>
-    ////public interface IAllGroupHeadsCollector
-    ////{
-    ////    // From AbstractAllGroupHeadsCollector{GH}
-    ////    FixedBitSet RetrieveGroupHeads(int maxDoc);
-    ////    int[] RetrieveGroupHeads();
-    ////    int GroupHeadsSize { get; }
-    ////    void Collect(int doc);
-    ////    bool AcceptsDocsOutOfOrder();
-
-    ////    // From Collector
-    ////    Scorer Scorer { set; }
-    ////    AtomicReaderContext NextReader { set; }
-    ////}
+    ///// <summary>
+    ///// LUCENENET specific interface used to apply covariance to GH
+    ///// </summary>
+    //public interface IAbstractAllGroupHeadsCollector<out GH>
+    //{
+    //    /// <summary>
+    //    /// 
+    //    /// </summary>
+    //    /// <param name="maxDoc">The maxDoc of the top level <see cref="Index.IndexReader"/></param>
+    //    /// <returns>a <see cref="FixedBitSet"/> containing all group heads.</returns>
+    //    FixedBitSet RetrieveGroupHeads(int maxDoc);
+
+    //    /// <summary>
+    //    /// 
+    //    /// </summary>
+    //    /// <returns>an int array containing all group heads. The size of the array is equal to number of collected unique groups.</returns>
+    //    int[] RetrieveGroupHeads();
+
+    //    /// <summary>
+    //    /// 
+    //    /// </summary>
+    //    /// <returns>the number of group heads found for a query.</returns>
+    //    int GroupHeadsSize { get; }
+    //}
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
index 0c8bc14..df240ee 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
@@ -1,4 +1,5 @@
 \ufeffusing System.Collections.Generic;
+using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -15,18 +16,18 @@ namespace Lucene.Net.Search.Grouping
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
-    public abstract class AbstractAllGroupsCollector<TGroupValue> : AbstractAllGroupsCollector
+    public abstract class AbstractAllGroupsCollector<TGroupValue> : Collector, IAbstractAllGroupsCollector<TGroupValue>
     {
         /// <summary>
         /// Returns the total number of groups for the executed search.
         /// This is a convenience method. The following code snippet has the same effect: <code>GetGroups().Count</code>
         /// </summary>
         /// <returns>The total number of groups for the executed search</returns>
-        public override int GroupCount
+        public virtual int GroupCount
         {
             get
             {
-                return Groups.Count;
+                return Groups.Count();
             }
         }
 
@@ -38,7 +39,7 @@ namespace Lucene.Net.Search.Grouping
         /// </para>
         /// </summary>
         /// <returns>the group values</returns>
-        public abstract ICollection<TGroupValue> Groups { get; }
+        public abstract IEnumerable<TGroupValue> Groups { get; }
 
 
         // Empty not necessary
@@ -56,30 +57,54 @@ namespace Lucene.Net.Search.Grouping
     }
 
     /// <summary>
-    /// LUCENENET specific class used to reference <see cref="AbstractAllGroupsCollector{TGroupValue}"/>
-    /// without refering to its generic closing type.
+    /// LUCENENET specific interface used to apply covariance to TGroupValue
     /// </summary>
-    public abstract class AbstractAllGroupsCollector : Collector
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface IAbstractAllGroupsCollector<out TGroupValue>
     {
         /// <summary>
         /// Returns the total number of groups for the executed search.
         /// This is a convenience method. The following code snippet has the same effect: <code>GetGroups().Count</code>
         /// </summary>
         /// <returns>The total number of groups for the executed search</returns>
-        public abstract int GroupCount { get; }
+        int GroupCount { get; }
 
+        /// <summary>
+        /// Returns the group values
+        /// <para>
+        /// This is an unordered collections of group values. For each group that matched the query there is a <see cref="BytesRef"/>
+        /// representing a group value.
+        /// </para>
+        /// </summary>
+        /// <returns>the group values</returns>
+        IEnumerable<TGroupValue> Groups { get; }
+    }
 
-        // Empty not necessary
-        public override Scorer Scorer
-        {
-            set
-            {
-            }
-        }
+    ///// <summary>
+    ///// LUCENENET specific class used to reference <see cref="AbstractAllGroupsCollector{TGroupValue}"/>
+    ///// without refering to its generic closing type.
+    ///// </summary>
+    //public abstract class AbstractAllGroupsCollector : Collector
+    //{
+    //    /// <summary>
+    //    /// Returns the total number of groups for the executed search.
+    //    /// This is a convenience method. The following code snippet has the same effect: <code>GetGroups().Count</code>
+    //    /// </summary>
+    //    /// <returns>The total number of groups for the executed search</returns>
+    //    public abstract int GroupCount { get; }
 
-        public override bool AcceptsDocsOutOfOrder()
-        {
-            return true;
-        }
-    }
+
+    //    // Empty not necessary
+    //    public override Scorer Scorer
+    //    {
+    //        set
+    //        {
+    //        }
+    //    }
+
+    //    public override bool AcceptsDocsOutOfOrder()
+    //    {
+    //        return true;
+    //    }
+    //}
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
index 8efafd2..0fb682d 100644
--- a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
@@ -22,7 +22,7 @@ namespace Lucene.Net.Search.Grouping
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
-    public abstract class AbstractFirstPassGroupingCollector<TGroupValue> : Collector
+    public abstract class AbstractFirstPassGroupingCollector<TGroupValue> : Collector, IAbstractFirstPassGroupingCollector<TGroupValue>
     {
         private readonly Sort groupSort;
         private readonly FieldComparator[] comparators;
@@ -88,7 +88,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupOffset">The offset in the collected groups</param>
         /// <param name="fillFields">Whether to fill to <see cref="SearchGroup.sortValues"/></param>
         /// <returns>top groups, starting from offset</returns>
-        public ICollection<SearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields)
+        public IEnumerable<ISearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields)
         {
 
             //System.out.println("FP.getTopGroups groupOffset=" + groupOffset + " fillFields=" + fillFields + " groupMap.size()=" + groupMap.size());
@@ -108,7 +108,7 @@ namespace Lucene.Net.Search.Grouping
                 BuildSortedSet();
             }
 
-            ICollection<SearchGroup<TGroupValue>> result = new List<SearchGroup<TGroupValue>>();
+            ICollection<ISearchGroup<TGroupValue>> result = new List<ISearchGroup<TGroupValue>>();
             int upto = 0;
             int sortFieldCount = groupSort.GetSort().Length;
             foreach (CollectedSearchGroup<TGroupValue> group in orderedGroups)
@@ -119,13 +119,13 @@ namespace Lucene.Net.Search.Grouping
                 }
                 //System.out.println("  group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
                 SearchGroup<TGroupValue> searchGroup = new SearchGroup<TGroupValue>();
-                searchGroup.groupValue = group.groupValue;
+                searchGroup.GroupValue = group.GroupValue;
                 if (fillFields)
                 {
-                    searchGroup.sortValues = new object[sortFieldCount];
+                    searchGroup.SortValues = new object[sortFieldCount];
                     for (int sortFieldIDX = 0; sortFieldIDX < sortFieldCount; sortFieldIDX++)
                     {
-                        searchGroup.sortValues[sortFieldIDX] = comparators[sortFieldIDX].Value(group.ComparatorSlot);
+                        searchGroup.SortValues[sortFieldIDX] = comparators[sortFieldIDX].Value(group.ComparatorSlot);
                     }
                 }
                 result.Add(searchGroup);
@@ -206,14 +206,14 @@ namespace Lucene.Net.Search.Grouping
 
                     // Add a new CollectedSearchGroup:
                     CollectedSearchGroup<TGroupValue> sg = new CollectedSearchGroup<TGroupValue>();
-                    sg.groupValue = CopyDocGroupValue(groupValue, default(TGroupValue));
+                    sg.GroupValue = CopyDocGroupValue(groupValue, default(TGroupValue));
                     sg.ComparatorSlot = groupMap.Count;
                     sg.TopDoc = docBase + doc;
                     foreach (FieldComparator fc in comparators)
                     {
                         fc.Copy(sg.ComparatorSlot, doc);
                     }
-                    groupMap[sg.groupValue] = sg;
+                    groupMap[sg.GroupValue] = sg;
 
                     if (groupMap.Count == topNGroups)
                     {
@@ -237,10 +237,10 @@ namespace Lucene.Net.Search.Grouping
                 }
                 Debug.Assert(orderedGroups.Count == topNGroups - 1);
 
-                groupMap.Remove(bottomGroup.groupValue);
+                groupMap.Remove(bottomGroup.GroupValue);
 
                 // reuse the removed CollectedSearchGroup
-                bottomGroup.groupValue = CopyDocGroupValue(groupValue, bottomGroup.groupValue);
+                bottomGroup.GroupValue = CopyDocGroupValue(groupValue, bottomGroup.GroupValue);
                 bottomGroup.TopDoc = docBase + doc;
 
                 foreach (FieldComparator fc in comparators)
@@ -248,7 +248,7 @@ namespace Lucene.Net.Search.Grouping
                     fc.Copy(bottomGroup.ComparatorSlot, doc);
                 }
 
-                groupMap[bottomGroup.groupValue] = bottomGroup;
+                groupMap[bottomGroup.GroupValue] = bottomGroup;
                 orderedGroups.Add(bottomGroup);
                 Debug.Assert(orderedGroups.Count == topNGroups);
 
@@ -424,4 +424,23 @@ namespace Lucene.Net.Search.Grouping
         protected abstract TGroupValue CopyDocGroupValue(TGroupValue groupValue, TGroupValue reuse);
 
     }
+
+    /// <summary>
+    /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface IAbstractFirstPassGroupingCollector<out TGroupValue>
+    {
+        // LUCENENET NOTE: We must use IEnumerable rather than ICollection here because we need
+        // this to be covariant
+        /// <summary>
+        /// Returns top groups, starting from offset.  This may
+        /// return null, if no groups were collected, or if the
+        /// number of unique groups collected is &lt;= offset.
+        /// </summary>
+        /// <param name="groupOffset">The offset in the collected groups</param>
+        /// <param name="fillFields">Whether to fill to <see cref="SearchGroup.sortValues"/></param>
+        /// <returns>top groups, starting from offset</returns>
+        IEnumerable<ISearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields);
+    }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
index 580617c..41b5837 100644
--- a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
@@ -26,19 +26,19 @@ namespace Lucene.Net.Search.Grouping
         protected readonly IDictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>> groupMap;
         private readonly int maxDocsPerGroup;
         protected AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>[] groupDocs;
-        private readonly ICollection<SearchGroup<TGroupValue>> groups;
+        private readonly IEnumerable<SearchGroup<TGroupValue>> groups;
         private readonly Sort withinGroupSort;
         private readonly Sort groupSort;
 
         private int totalHitCount;
         private int totalGroupedHitCount;
 
-        public AbstractSecondPassGroupingCollector(ICollection<SearchGroup<TGroupValue>> groups, Sort groupSort, Sort withinGroupSort,
+        public AbstractSecondPassGroupingCollector(IEnumerable<SearchGroup<TGroupValue>> groups, Sort groupSort, Sort withinGroupSort,
                                                    int maxDocsPerGroup, bool getScores, bool getMaxScores, bool fillSortFields)
         {
 
             //System.out.println("SP init");
-            if (groups.Count == 0)
+            if (groups.Count() == 0)
             {
                 throw new ArgumentException("no groups to collect (groups.size() is 0)");
             }
@@ -47,7 +47,7 @@ namespace Lucene.Net.Search.Grouping
             this.withinGroupSort = withinGroupSort;
             this.groups = groups;
             this.maxDocsPerGroup = maxDocsPerGroup;
-            groupMap = new Dictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>>(groups.Count);
+            groupMap = new Dictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>>(groups.Count());
 
             foreach (SearchGroup<TGroupValue> group in groups)
             {
@@ -64,7 +64,7 @@ namespace Lucene.Net.Search.Grouping
                     // Sort by fields
                     collector = TopFieldCollector.Create(withinGroupSort, maxDocsPerGroup, fillSortFields, getScores, getMaxScores, true);
                 }
-                groupMap[group.groupValue] = new AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>(group.groupValue, collector);
+                groupMap[group.GroupValue] = new AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>(group.GroupValue, collector);
             }
         }
 
@@ -118,20 +118,20 @@ namespace Lucene.Net.Search.Grouping
 
         public TopGroups<TGroupValue> GetTopGroups(int withinGroupOffset)
         {
-            GroupDocs<TGroupValue>[] groupDocsResult = new GroupDocs<TGroupValue>[groups.Count];
+            GroupDocs<TGroupValue>[] groupDocsResult = new GroupDocs<TGroupValue>[groups.Count()];
 
             int groupIDX = 0;
             float maxScore = float.MinValue;
             foreach (var group in groups)
             {
-                AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> groupDocs = groupMap.ContainsKey(group.groupValue) ? groupMap[group.groupValue] : null;
+                AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> groupDocs = groupMap.ContainsKey(group.GroupValue) ? groupMap[group.GroupValue] : null;
                 TopDocs topDocs = groupDocs.collector.TopDocs(withinGroupOffset, maxDocsPerGroup);
                 groupDocsResult[groupIDX++] = new GroupDocs<TGroupValue>(float.NaN,
                                                                               topDocs.MaxScore,
                                                                               topDocs.TotalHits,
                                                                               topDocs.ScoreDocs,
                                                                               groupDocs.groupValue,
-                                                                              group.sortValues);
+                                                                              group.SortValues);
                 maxScore = Math.Max(maxScore, topDocs.MaxScore);
             }
 
@@ -167,4 +167,13 @@ namespace Lucene.Net.Search.Grouping
             }
         }
     }
+
+    /// <summary>
+    /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface IAbstractSecondPassGroupingCollector<out TGroupValue>
+    {
+        ITopGroups<TGroupValue> GetTopGroups(int withinGroupOffset);
+    }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
index 638f36b..c5c7623 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
@@ -39,7 +39,7 @@ namespace Lucene.Net.Search.Grouping.Function
             this.groupBy = groupBy;
         }
 
-        public override ICollection<MutableValue> Groups
+        public override IEnumerable<MutableValue> Groups
         {
             get
             {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
index 2e84920..3d5dc0a 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
@@ -36,7 +36,7 @@ namespace Lucene.Net.Search.Grouping.Function
             groupMap = new LurchTable<MutableValue, GroupCount>(1 << 4);
             foreach (SearchGroup<MutableValue> group in groups)
             {
-                groupMap[group.groupValue] = new GroupCount(group.groupValue);
+                groupMap[group.GroupValue] = new GroupCount(group.GroupValue);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/GroupDocs.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupDocs.cs b/src/Lucene.Net.Grouping/GroupDocs.cs
index 29d227e..cc1a7c6 100644
--- a/src/Lucene.Net.Grouping/GroupDocs.cs
+++ b/src/Lucene.Net.Grouping/GroupDocs.cs
@@ -24,39 +24,39 @@ namespace Lucene.Net.Search.Grouping
     /// 
     /// @lucene.experimental 
     /// </summary>
-    public class GroupDocs<TGroupValue>
+    public class GroupDocs<TGroupValue> : IGroupDocs<TGroupValue>
     {
         /// <summary>
         /// The groupField value for all docs in this group; this
         /// may be null if hits did not have the groupField. 
         /// </summary>
-        public readonly TGroupValue GroupValue;
+        public TGroupValue GroupValue { get; private set; }
 
         /// <summary>
         /// Max score in this group
         /// </summary>
-        public readonly float MaxScore;
+        public float MaxScore { get; private set; }
 
         /// <summary>
         /// Overall aggregated score of this group (currently only set by join queries). 
         /// </summary>
-        public readonly float Score;
+        public float Score { get; private set; }
 
         /// <summary>
-        /// Hits; this may be {@link org.apache.lucene.search.FieldDoc} instances if the
+        /// Hits; this may be <see cref="FieldDoc"/> instances if the
         /// withinGroupSort sorted by fields. 
         /// </summary>
-        public readonly ScoreDoc[] ScoreDocs;
+        public ScoreDoc[] ScoreDocs { get; private set; }
 
         /// <summary>
         /// Total hits within this group
         /// </summary>
-        public readonly int TotalHits;
+        public int TotalHits { get; private set; }
 
         /// <summary>
-        /// Matches the groupSort passed to {@link AbstractFirstPassGroupingCollector}. 
+        /// Matches the groupSort passed to <see cref="AbstractFirstPassGroupingCollector{TGroupValue}"/>. 
         /// </summary>
-        public readonly object[] GroupSortValues;
+        public object[] GroupSortValues { get; private set; }
 
         public GroupDocs(float score, float maxScore, int totalHits, ScoreDoc[] scoreDocs, TGroupValue groupValue, object[] groupSortValues)
         {
@@ -68,4 +68,43 @@ namespace Lucene.Net.Search.Grouping
             GroupSortValues = groupSortValues;
         }
     }
+
+    /// <summary>
+    /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface IGroupDocs<out TGroupValue>
+    {
+        /// <summary>
+        /// The groupField value for all docs in this group; this
+        /// may be null if hits did not have the groupField. 
+        /// </summary>
+        TGroupValue GroupValue { get; }
+
+        /// <summary>
+        /// Max score in this group
+        /// </summary>
+        float MaxScore { get; }
+
+        /// <summary>
+        /// Overall aggregated score of this group (currently only set by join queries). 
+        /// </summary>
+        float Score { get; }
+
+        /// <summary>
+        /// Hits; this may be <see cref="FieldDoc"/> instances if the
+        /// withinGroupSort sorted by fields. 
+        /// </summary>
+        ScoreDoc[] ScoreDocs { get; }
+
+        /// <summary>
+        /// Total hits within this group
+        /// </summary>
+        int TotalHits { get; }
+
+        /// <summary>
+        /// Matches the groupSort passed to <see cref="AbstractFirstPassGroupingCollector{TGroupValue}"/>. 
+        /// </summary>
+        object[] GroupSortValues { get; }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/GroupingSearch.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupingSearch.cs b/src/Lucene.Net.Grouping/GroupingSearch.cs
index 28b5381..56554f6 100644
--- a/src/Lucene.Net.Grouping/GroupingSearch.cs
+++ b/src/Lucene.Net.Grouping/GroupingSearch.cs
@@ -41,7 +41,7 @@ namespace Lucene.Net.Search.Grouping
         private bool allGroupHeads;
         private int initialSize = 128;
 
-        private ICollection /* Collection<?> */ matchingGroups;
+        private IList /* Collection<?> */ matchingGroups;
         private Bits matchingGroupHeads;
 
         /**
@@ -97,7 +97,7 @@ namespace Lucene.Net.Search.Grouping
          * @return the grouped result as a {@link TopGroups} instance
          * @throws IOException If any I/O related errors occur
          */
-        public TopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+        public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
         {
             return Search<TGroupValue>(searcher, null, query, groupOffset, groupLimit);
         }
@@ -113,7 +113,7 @@ namespace Lucene.Net.Search.Grouping
          * @return the grouped result as a {@link TopGroups} instance
          * @throws IOException If any I/O related errors occur
          */
-        public TopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             if (groupField != null || groupFunction != null)
             {
@@ -129,147 +129,151 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        protected TopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        protected ITopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
-            // LUCENENET TODO: Finish
-            return null;
-            //int topN = groupOffset + groupLimit;
-            //AbstractFirstPassGroupingCollector<TGroupValue> firstPassCollector;
-            //AbstractAllGroupsCollector<TGroupValue> allGroupsCollector;
-            //AbstractAllGroupHeadsCollector allGroupHeadsCollector;
-            //if (groupFunction != null)
-            //{
-            //    firstPassCollector = new FunctionFirstPassGroupingCollector(groupFunction, valueSourceContext, groupSort, topN);
-            //    if (allGroups)
-            //    {
-            //        allGroupsCollector = new FunctionAllGroupsCollector(groupFunction, valueSourceContext);
-            //    }
-            //    else
-            //    {
-            //        allGroupsCollector = null;
-            //    }
-            //    if (allGroupHeads)
-            //    {
-            //        allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(groupFunction, valueSourceContext, sortWithinGroup);
-            //    }
-            //    else
-            //    {
-            //        allGroupHeadsCollector = null;
-            //    }
-            //}
-            //else
-            //{
-            //    firstPassCollector = new TermFirstPassGroupingCollector(groupField, groupSort, topN);
-            //    if (allGroups)
-            //    {
-            //        allGroupsCollector = new TermAllGroupsCollector(groupField, initialSize);
-            //    }
-            //    else
-            //    {
-            //        allGroupsCollector = null;
-            //    }
-            //    if (allGroupHeads)
-            //    {
-            //        allGroupHeadsCollector = TermAllGroupHeadsCollector.Create(groupField, sortWithinGroup, initialSize);
-            //    }
-            //    else
-            //    {
-            //        allGroupHeadsCollector = null;
-            //    }
-            //}
-
-            //Collector firstRound;
-            //if (allGroupHeads || allGroups)
-            //{
-            //    List<Collector> collectors = new List<Collector>();
-            //    collectors.Add(firstPassCollector);
-            //    if (allGroups)
-            //    {
-            //        collectors.Add(allGroupsCollector);
-            //    }
-            //    if (allGroupHeads)
-            //    {
-            //        collectors.Add(allGroupHeadsCollector);
-            //    }
-            //    firstRound = MultiCollector.Wrap(collectors.ToArray(/* new Collector[collectors.size()] */));
-            //}
-            //else
-            //{
-            //    firstRound = firstPassCollector;
-            //}
-
-            //CachingCollector cachedCollector = null;
-            //if (maxCacheRAMMB != null || maxDocsToCache != null)
-            //{
-            //    if (maxCacheRAMMB != null)
-            //    {
-            //        cachedCollector = CachingCollector.Create(firstRound, cacheScores, maxCacheRAMMB.Value);
-            //    }
-            //    else
-            //    {
-            //        cachedCollector = CachingCollector.Create(firstRound, cacheScores, maxDocsToCache.Value);
-            //    }
-            //    searcher.Search(query, filter, cachedCollector);
-            //}
-            //else
-            //{
-            //    searcher.Search(query, filter, firstRound);
-            //}
-
-            //if (allGroups)
-            //{
-            //    matchingGroups = (ICollection)allGroupsCollector.GetGroups();
-            //}
-            //else
-            //{
-            //    matchingGroups = (ICollection)Collections.EmptyList<TGroupValue>();
-            //}
-            //if (allGroupHeads)
-            //{
-            //    matchingGroupHeads = allGroupHeadsCollector.RetrieveGroupHeads(searcher.IndexReader.MaxDoc);
-            //}
-            //else
-            //{
-            //    matchingGroupHeads = new Bits_MatchNoBits(searcher.IndexReader.MaxDoc);
-            //}
-
-            //ICollection<SearchGroup<TGroupValue>> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
-            //if (topSearchGroups == null)
-            //{
-            //    return new TopGroups<TGroupValue>(new SortField[0], new SortField[0], 0, 0, new GroupDocs<TGroupValue>[0], float.NaN);
-            //}
-
-            //int topNInsideGroup = groupDocsOffset + groupDocsLimit;
-            //AbstractSecondPassGroupingCollector<TGroupValue> secondPassCollector;
-            //if (groupFunction != null)
-            //{
-            //    secondPassCollector = new FunctionSecondPassGroupingCollector(topSearchGroups as ICollection<SearchGroup<MutableValue>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext);
-            //}
-            //else
-            //{
-            //    secondPassCollector = new TermSecondPassGroupingCollector(groupField, topSearchGroups as ICollection<SearchGroup<BytesRef>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
-            //}
-
-            //if (cachedCollector != null && cachedCollector.Cached)
-            //{
-            //    cachedCollector.Replay(secondPassCollector);
-            //}
-            //else
-            //{
-            //    searcher.Search(query, filter, secondPassCollector);
-            //}
-
-            //if (allGroups)
-            //{
-            //    return new TopGroups<TGroupValue>(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
-            //}
-            //else
-            //{
-            //    return secondPassCollector.GetTopGroups(groupDocsOffset);
-            //}
+            int topN = groupOffset + groupLimit;
+            IAbstractFirstPassGroupingCollector<TGroupValue> firstPassCollector;
+            IAbstractAllGroupsCollector<TGroupValue> allGroupsCollector;
+            AbstractAllGroupHeadsCollector allGroupHeadsCollector;
+            if (groupFunction != null)
+            {
+                firstPassCollector = (IAbstractFirstPassGroupingCollector<TGroupValue>)new FunctionFirstPassGroupingCollector(groupFunction, valueSourceContext, groupSort, topN);
+                if (allGroups)
+                {
+                    allGroupsCollector = (IAbstractAllGroupsCollector<TGroupValue>)new FunctionAllGroupsCollector(groupFunction, valueSourceContext);
+                }
+                else
+                {
+                    allGroupsCollector = null;
+                }
+                if (allGroupHeads)
+                {
+                    allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(groupFunction, valueSourceContext, sortWithinGroup);
+                }
+                else
+                {
+                    allGroupHeadsCollector = null;
+                }
+            }
+            else
+            {
+                firstPassCollector = (IAbstractFirstPassGroupingCollector<TGroupValue>)new TermFirstPassGroupingCollector(groupField, groupSort, topN);
+                if (allGroups)
+                {
+                    allGroupsCollector = (IAbstractAllGroupsCollector<TGroupValue>)new TermAllGroupsCollector(groupField, initialSize);
+                }
+                else
+                {
+                    allGroupsCollector = null;
+                }
+                if (allGroupHeads)
+                {
+                    allGroupHeadsCollector = TermAllGroupHeadsCollector.Create(groupField, sortWithinGroup, initialSize);
+                }
+                else
+                {
+                    allGroupHeadsCollector = null;
+                }
+            }
+
+            Collector firstRound;
+            if (allGroupHeads || allGroups)
+            {
+                List<Collector> collectors = new List<Collector>();
+                // LUCENENET TODO: Make the Collector abstract class into an interface
+                // so we can remove the casting here
+                collectors.Add((Collector)firstPassCollector);
+                if (allGroups)
+                {
+                    // LUCENENET TODO: Make the Collector abstract class into an interface
+                    // so we can remove the casting here
+                    collectors.Add((Collector)allGroupsCollector);
+                }
+                if (allGroupHeads)
+                {
+                    collectors.Add(allGroupHeadsCollector);
+                }
+                firstRound = MultiCollector.Wrap(collectors.ToArray(/* new Collector[collectors.size()] */));
+            }
+            else
+            {
+                // LUCENENET TODO: Make the Collector abstract class into an interface
+                // so we can remove the casting here
+                firstRound = (Collector)firstPassCollector;
+            }
+
+            CachingCollector cachedCollector = null;
+            if (maxCacheRAMMB != null || maxDocsToCache != null)
+            {
+                if (maxCacheRAMMB != null)
+                {
+                    cachedCollector = CachingCollector.Create(firstRound, cacheScores, maxCacheRAMMB.Value);
+                }
+                else
+                {
+                    cachedCollector = CachingCollector.Create(firstRound, cacheScores, maxDocsToCache.Value);
+                }
+                searcher.Search(query, filter, cachedCollector);
+            }
+            else
+            {
+                searcher.Search(query, filter, firstRound);
+            }
+
+            if (allGroups)
+            {
+                matchingGroups = (IList)allGroupsCollector.Groups;
+            }
+            else
+            {
+                matchingGroups = new List<TGroupValue>();
+            }
+            if (allGroupHeads)
+            {
+                matchingGroupHeads = allGroupHeadsCollector.RetrieveGroupHeads(searcher.IndexReader.MaxDoc);
+            }
+            else
+            {
+                matchingGroupHeads = new Bits_MatchNoBits(searcher.IndexReader.MaxDoc);
+            }
+
+            IEnumerable<ISearchGroup<TGroupValue>> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
+            if (topSearchGroups == null)
+            {
+                return new TopGroups<TGroupValue>(new SortField[0], new SortField[0], 0, 0, new GroupDocs<TGroupValue>[0], float.NaN);
+            }
+
+            int topNInsideGroup = groupDocsOffset + groupDocsLimit;
+            IAbstractSecondPassGroupingCollector<TGroupValue> secondPassCollector;
+            if (groupFunction != null)
+            {
+                secondPassCollector = (IAbstractSecondPassGroupingCollector<TGroupValue>)new FunctionSecondPassGroupingCollector(topSearchGroups as ICollection<SearchGroup<MutableValue>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext);
+            }
+            else
+            {
+                secondPassCollector = (IAbstractSecondPassGroupingCollector<TGroupValue>)new TermSecondPassGroupingCollector(groupField, topSearchGroups as ICollection<SearchGroup<BytesRef>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
+            }
+
+            if (cachedCollector != null && cachedCollector.Cached)
+            {
+                cachedCollector.Replay((Collector)secondPassCollector);
+            }
+            else
+            {
+                searcher.Search(query, filter, (Collector)secondPassCollector);
+            }
+
+            if (allGroups)
+            {
+                return new TopGroups<TGroupValue>(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
+            }
+            else
+            {
+                return secondPassCollector.GetTopGroups(groupDocsOffset);
+            }
         }
 
-        protected TopGroups<T> GroupByDocBlock<T>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        protected ITopGroups<T> GroupByDocBlock<T>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             int topN = groupOffset + groupLimit;
             BlockGroupingCollector c = new BlockGroupingCollector(groupSort, topN, includeScores, groupEndDocs);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index 6ab902f..693e513 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -14,21 +14,21 @@ namespace Lucene.Net.Search.Grouping
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
-    public class SearchGroup<TGroupValue>
+    public class SearchGroup<TGroupValue> : ISearchGroup<TGroupValue>
     {
         /** The value that defines this group  */
-        public TGroupValue groupValue;
+        public TGroupValue GroupValue { get; set; }
 
         /** The sort values used during sorting. These are the
          *  groupSort field values of the highest rank document
          *  (by the groupSort) within the group.  Can be
          * <code>null</code> if <code>fillFields=false</code> had
          * been passed to {@link AbstractFirstPassGroupingCollector#getTopGroups} */
-        public object[] sortValues;
+        public object[] SortValues { get; set; }
 
         public override string ToString()
         {
-            return ("SearchGroup(groupValue=" + groupValue + " sortValues=" + Arrays.ToString(sortValues) + ")");
+            return ("SearchGroup(groupValue=" + GroupValue + " sortValues=" + Arrays.ToString(SortValues) + ")");
         }
 
         public override bool Equals(object o)
@@ -38,14 +38,14 @@ namespace Lucene.Net.Search.Grouping
 
             SearchGroup<TGroupValue> that = (SearchGroup<TGroupValue>)o;
 
-            if (groupValue == null)
+            if (GroupValue == null)
             {
-                if (that.groupValue != null)
+                if (that.GroupValue != null)
                 {
                     return false;
                 }
             }
-            else if (!groupValue.Equals(that.groupValue))
+            else if (!GroupValue.Equals(that.GroupValue))
             {
                 return false;
             }
@@ -55,7 +55,7 @@ namespace Lucene.Net.Search.Grouping
 
         public override int GetHashCode()
         {
-            return groupValue != null ? groupValue.GetHashCode() : 0;
+            return GroupValue != null ? GroupValue.GetHashCode() : 0;
         }
 
         private class ShardIter<T>
@@ -74,7 +74,7 @@ namespace Lucene.Net.Search.Grouping
             {
                 Debug.Assert(iter.MoveNext());
                 SearchGroup<T> group = iter.Current;
-                if (group.sortValues == null)
+                if (group.SortValues == null)
                 {
                     throw new ArgumentException("group.sortValues is null; you must pass fillFields=true to the first pass collector");
                 }
@@ -224,7 +224,7 @@ namespace Lucene.Net.Search.Grouping
                 while (shard.iter.MoveNext())
                 {
                     SearchGroup<T> group = shard.Next();
-                    MergedGroup<T> mergedGroup = groupsSeen.ContainsKey(group.groupValue) ? groupsSeen[group.groupValue] : null;
+                    MergedGroup<T> mergedGroup = groupsSeen.ContainsKey(group.GroupValue) ? groupsSeen[group.GroupValue] : null;
                     bool isNew = mergedGroup == null;
                     //System.out.println("    next group=" + (group.groupValue == null ? "null" : ((BytesRef) group.groupValue).utf8ToString()) + " sort=" + Arrays.toString(group.sortValues));
 
@@ -232,11 +232,11 @@ namespace Lucene.Net.Search.Grouping
                     {
                         // Start a new group:
                         //System.out.println("      new");
-                        mergedGroup = new MergedGroup<T>(group.groupValue);
+                        mergedGroup = new MergedGroup<T>(group.GroupValue);
                         mergedGroup.minShardIndex = shard.shardIndex;
-                        Debug.Assert(group.sortValues != null);
-                        mergedGroup.topValues = group.sortValues;
-                        groupsSeen[group.groupValue] = mergedGroup;
+                        Debug.Assert(group.SortValues != null);
+                        mergedGroup.topValues = group.SortValues;
+                        groupsSeen[group.GroupValue] = mergedGroup;
                         mergedGroup.inQueue = true;
                         queue.Add(mergedGroup);
                     }
@@ -252,7 +252,7 @@ namespace Lucene.Net.Search.Grouping
                         bool competes = false;
                         for (int compIDX = 0; compIDX < groupComp.comparators.Length; compIDX++)
                         {
-                            int cmp = groupComp.reversed[compIDX] * groupComp.comparators[compIDX].CompareValues(group.sortValues[compIDX],
+                            int cmp = groupComp.reversed[compIDX] * groupComp.comparators[compIDX].CompareValues(group.SortValues[compIDX],
                                                                                                                        mergedGroup.topValues[compIDX]);
                             if (cmp < 0)
                             {
@@ -283,7 +283,7 @@ namespace Lucene.Net.Search.Grouping
                             {
                                 queue.Remove(mergedGroup);
                             }
-                            mergedGroup.topValues = group.sortValues;
+                            mergedGroup.topValues = group.SortValues;
                             mergedGroup.minShardIndex = shard.shardIndex;
                             queue.Add(mergedGroup);
                             mergedGroup.inQueue = true;
@@ -335,8 +335,8 @@ namespace Lucene.Net.Search.Grouping
                     if (count++ >= offset)
                     {
                         SearchGroup<T> newGroup = new SearchGroup<T>();
-                        newGroup.groupValue = group.groupValue;
-                        newGroup.sortValues = group.topValues;
+                        newGroup.GroupValue = group.groupValue;
+                        newGroup.SortValues = group.topValues;
                         newTopGroups.Add(newGroup);
                         if (newTopGroups.Count == topN)
                         {
@@ -385,4 +385,15 @@ namespace Lucene.Net.Search.Grouping
             }
         }
     }
+
+    /// <summary>
+    /// LUCENENET specific interface used to provide covariance
+    /// with the TGroupValue type
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface ISearchGroup<out TGroupValue>
+    {
+        TGroupValue GroupValue { get; }
+        object[] SortValues { get; set; }
+    }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
index 7693d93..ef33aa5 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
@@ -83,7 +83,7 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        public override ICollection<BytesRef> Groups
+        public override IEnumerable<BytesRef> Groups
         {
             get
             {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
index d6f6bab..502b0ea 100644
--- a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
@@ -41,7 +41,7 @@ namespace Lucene.Net.Search.Grouping.Terms
             this.groups = new List<GroupCount>(groups.Count);
             foreach (SearchGroup<BytesRef> group in groups)
             {
-                this.groups.Add(new GroupCount(group.groupValue));
+                this.groups.Add(new GroupCount(group.GroupValue));
             }
             ordSet = new SentinelIntSet(groups.Count, -2);
             groupCounts = new GroupCount[ordSet.Keys.Length];

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/0a137bea/src/Lucene.Net.Grouping/TopGroups.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/TopGroups.cs b/src/Lucene.Net.Grouping/TopGroups.cs
index 091103d..b5d5c65 100644
--- a/src/Lucene.Net.Grouping/TopGroups.cs
+++ b/src/Lucene.Net.Grouping/TopGroups.cs
@@ -24,39 +24,39 @@ namespace Lucene.Net.Search.Grouping
     /// 
     /// @lucene.experimental 
     /// </summary>
-    public class TopGroups<TGroupValue>
+    public class TopGroups<TGroupValue> : ITopGroups<TGroupValue>
     {
         /// <summary>
         /// Number of documents matching the search </summary>
-        public readonly int TotalHitCount;
+        public int TotalHitCount { get; private set; }
 
         /// <summary>
         /// Number of documents grouped into the topN groups </summary>
-        public readonly int TotalGroupedHitCount;
+        public int TotalGroupedHitCount { get; private set; }
 
         /// <summary>
-        /// The total number of unique groups. If <code>null</code> this value is not computed. </summary>
-        public readonly int? TotalGroupCount;
+        /// The total number of unique groups. If <c>null</c> this value is not computed. </summary>
+        public int? TotalGroupCount { get; private set; }
 
         /// <summary>
         /// Group results in groupSort order </summary>
-        public readonly GroupDocs<TGroupValue>[] Groups;
+        public IGroupDocs<TGroupValue>[] Groups { get; private set; }
 
         /// <summary>
         /// How groups are sorted against each other </summary>
-        public readonly SortField[] GroupSort;
+        public SortField[] GroupSort { get; private set; }
 
         /// <summary>
         /// How docs are sorted within each group </summary>
-        public readonly SortField[] WithinGroupSort;
+        public SortField[] WithinGroupSort { get; private set; }
 
         /// <summary>
         /// Highest score across all hits, or
-        ///  <code>Float.NaN</code> if scores were not computed. 
+        /// <see cref="float.NaN"/> if scores were not computed. 
         /// </summary>
-        public readonly float MaxScore;
+        public float MaxScore { get; private set; }
 
-        public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<TGroupValue>[] groups, float maxScore)
+        public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, IGroupDocs<TGroupValue>[] groups, float maxScore)
         {
             GroupSort = groupSort;
             WithinGroupSort = withinGroupSort;
@@ -67,7 +67,7 @@ namespace Lucene.Net.Search.Grouping
             MaxScore = maxScore;
         }
 
-        public TopGroups(TopGroups<TGroupValue> oldTopGroups, int? totalGroupCount)
+        public TopGroups(ITopGroups<TGroupValue> oldTopGroups, int? totalGroupCount)
         {
             GroupSort = oldTopGroups.GroupSort;
             WithinGroupSort = oldTopGroups.WithinGroupSort;
@@ -245,4 +245,42 @@ namespace Lucene.Net.Search.Grouping
             return new TopGroups<T>(groupSort.GetSort(), docSort == null ? null : docSort.GetSort(), totalHitCount, totalGroupedHitCount, mergedGroupDocs, totalMaxScore);
         }
     }
+
+    /// <summary>
+    /// LUCENENET specific interface used to provide covariance
+    /// with the TGroupValue type
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface ITopGroups<out TGroupValue>
+    {
+        /// <summary>
+        /// Number of documents matching the search </summary>
+        int TotalHitCount { get; }
+
+        /// <summary>
+        /// Number of documents grouped into the topN groups </summary>
+        int TotalGroupedHitCount { get; }
+
+        /// <summary>
+        /// The total number of unique groups. If <c>null</c> this value is not computed. </summary>
+        int? TotalGroupCount { get; }
+
+        /// <summary>
+        /// Group results in groupSort order </summary>
+        IGroupDocs<TGroupValue>[] Groups { get; }
+
+        /// <summary>
+        /// How groups are sorted against each other </summary>
+        SortField[] GroupSort { get; }
+
+        /// <summary>
+        /// How docs are sorted within each group </summary>
+        SortField[] WithinGroupSort { get; }
+
+        /// <summary>
+        /// Highest score across all hits, or
+        /// <see cref="float.NaN"/> if scores were not computed. 
+        /// </summary>
+        float MaxScore { get; }
+    }
 }
\ No newline at end of file


[08/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Core/Support/TreeSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/TreeSet.cs b/src/Lucene.Net.Core/Support/TreeSet.cs
new file mode 100644
index 0000000..4ce8831
--- /dev/null
+++ b/src/Lucene.Net.Core/Support/TreeSet.cs
@@ -0,0 +1,3752 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using Lucene.Net.Support.C5;
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support
+{
+    /// <summary>
+    /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,
+    /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag`1"/> for a version 
+    /// with bag semantics. <see cref="T:C5.TreeDictionary`2"/> for a sorted dictionary 
+    /// based on this tree implementation.
+    /// <i>
+    /// The comparer (sorting order) may be either natural, because the item type is comparable 
+    /// (generic: <see cref="T:C5.IComparable`1"/> or non-generic: System.IComparable) or it can
+    /// be external and supplied by the user in the constructor.</i>
+    ///
+    /// <i>TODO: describe performance here</i>
+    /// <i>TODO: discuss persistence and its useful usage modes. Warn about the space
+    /// leak possible with other usage modes.</i>
+    /// </summary>
+    [Serializable]
+    public class TreeSet<T> : SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>
+    {
+        #region Fields
+
+        SCG.IComparer<T> comparer;
+
+        Node root;
+
+        //TODO: wonder if we should remove that
+        int blackdepth = 0;
+
+        //We double these stacks for the iterative add and remove on demand
+        //TODO: refactor dirs[] into bool fields on Node (?)
+        private int[] dirs = new int[2];
+
+        private Node[] path = new Node[2];
+
+        //TODO: refactor into separate class
+        bool isSnapShot = false;
+
+        int generation;
+
+        bool isValid = true;
+
+        SnapRef snapList;
+
+        #endregion
+
+        #region Events
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+        #endregion
+        #region Util
+
+        /// <summary>
+        /// Fetch the left child of n taking node-copying persistence into
+        /// account if relevant. 
+        /// </summary>
+        /// <param name="n"></param>
+        /// <returns></returns>
+        private Node left(Node n)
+        {
+            if (isSnapShot)
+            {
+
+                if (n.lastgeneration >= generation && n.leftnode)
+                    return n.oldref;
+            }
+            return n.left;
+        }
+
+
+        private Node right(Node n)
+        {
+            if (isSnapShot)
+            {
+
+                if (n.lastgeneration >= generation && !n.leftnode)
+                    return n.oldref;
+            }
+            return n.right;
+        }
+
+
+        //This method should be called by methods that use the internal 
+        //traversal stack, unless certain that there is room enough
+        private void stackcheck()
+        {
+            while (dirs.Length < 2 * blackdepth)
+            {
+                dirs = new int[2 * dirs.Length];
+                path = new Node[2 * dirs.Length];
+            }
+        }
+
+        #endregion
+
+        #region Node nested class
+
+
+        /// <summary>
+        /// The type of node in a Red-Black binary tree
+        /// </summary>
+        [Serializable]
+        class Node
+        {
+            public bool red = true;
+
+            public T item;
+
+            public Node left;
+
+            public Node right;
+
+            public int size = 1;
+
+            //TODO: move everything into (separate) Extra
+            public int generation;
+
+            public int lastgeneration = -1;
+
+            public Node oldref;
+
+            public bool leftnode;
+
+            /// <summary>
+            /// Update a child pointer
+            /// </summary>
+            /// <param name="cursor"></param>
+            /// <param name="leftnode"></param>
+            /// <param name="child"></param>
+            /// <param name="maxsnapid"></param>
+            /// <param name="generation"></param>
+            /// <returns>True if node was *copied*</returns>
+            internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)
+            {
+                Node oldref = leftnode ? cursor.left : cursor.right;
+
+                if (child == oldref)
+                    return false;
+
+                bool retval = false;
+
+                if (cursor.generation <= maxsnapid)
+                {
+                    if (cursor.lastgeneration == -1)
+                    {
+                        cursor.leftnode = leftnode;
+                        cursor.lastgeneration = maxsnapid;
+                        cursor.oldref = oldref;
+                    }
+                    else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)
+                    {
+                        CopyNode(ref cursor, maxsnapid, generation);
+                        retval = true;
+                    }
+                }
+
+                if (leftnode)
+                    cursor.left = child;
+                else
+                    cursor.right = child;
+
+                return retval;
+            }
+
+
+            //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will 
+            //always be used in the old copy of cursor. Therefore, after 
+            //making the clone, we should update the old copy by restoring
+            //the child pointer and setting extra to null.
+            //OTOH then we cannot clean up unused Extra objects unless we link
+            //them together in a doubly linked list.
+            public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)
+            {
+                if (cursor.generation <= maxsnapid)
+                {
+                    cursor = (Node)(cursor.MemberwiseClone());
+                    cursor.generation = generation;
+                    cursor.lastgeneration = -1;
+                    return true;
+                }
+
+                return false;
+            }
+        }
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Create a red-black tree collection with natural comparer and item equalityComparer.
+        /// We assume that if <code>T</code> is comparable, its default equalityComparer 
+        /// will be compatible with the comparer.
+        /// </summary>
+        /// <exception cref="NotComparableException">If <code>T</code> is not comparable.
+        /// </exception>
+		public TreeSet(MemoryType memoryType = MemoryType.Normal) : this(SCG.Comparer<T>.Default, EqualityComparer<T>.Default, memoryType) { }
+
+
+        /// <summary>
+        /// Create a red-black tree collection with an external comparer. 
+        /// <para>The itemequalityComparer will be a compatible 
+        /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the 
+        /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)
+        /// is unlikely to be compatible with the external comparer. This makes the
+        /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags
+        /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)
+        /// </para>
+        /// </summary>
+        /// <param name="comparer">The external comparer</param>
+		/// <param name = "memoryType"></param>
+		public TreeSet(SCG.IComparer<T> comparer, MemoryType memoryType = MemoryType.Normal) : this(comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }
+
+        /// <summary>
+        /// Create a red-black tree collection with an external comparer and an external
+        /// item equalityComparer, assumed consistent.
+        /// </summary>
+        /// <param name="comparer">The external comparer</param>
+        /// <param name="equalityComparer">The external item equalitySCG.Comparer</param>
+		/// <param name = "memoryType"></param>
+		public TreeSet(SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> equalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(equalityComparer, memoryType)
+        {
+            if (comparer == null)
+                throw new NullReferenceException("Item comparer cannot be null");
+
+            if (memoryType != MemoryType.Normal)
+                throw new Exception("TreeSet doesn't support MemoryType Strict or Safe");
+
+            this.comparer = comparer;
+        }
+
+        #endregion
+
+        #region TreeSet.Enumerator nested class
+
+        /// <summary>
+        /// An enumerator for a red-black tree collection. Based on an explicit stack
+        /// of subtrees waiting to be enumerated. Currently only used for the tree set 
+        /// enumerators (tree bag enumerators use an iterator block based enumerator).
+        /// </summary>
+        [Serializable]
+        internal class Enumerator : SCG.IEnumerator<T>
+        {
+            #region Private Fields
+            TreeSet<T> tree;
+
+            bool valid = false;
+
+            int stamp;
+
+            T current;
+
+            Node cursor;
+
+            Node[] path; // stack of nodes
+
+            int level = 0;
+            #endregion
+            /// <summary>
+            /// Create a tree enumerator
+            /// </summary>
+            /// <param name="tree">The red-black tree to enumerate</param>
+            public Enumerator(TreeSet<T> tree)
+            {
+                this.tree = tree;
+                stamp = tree.stamp;
+                path = new Node[2 * tree.blackdepth];
+                cursor = new Node();
+                cursor.right = tree.root;
+            }
+
+
+            /// <summary>
+            /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+            /// </summary>
+            /// <value>The current item of the enumerator.</value>
+            public T Current
+            {
+                get
+                {
+                    if (valid)
+                        return current;
+                    else
+                        throw new InvalidOperationException();
+                }
+            }
+
+
+            //Maintain a stack of nodes that are roots of
+            //subtrees not completely exported yet. Invariant:
+            //The stack nodes together with their right subtrees
+            //consists of exactly the items we have not passed
+            //yet (the top of the stack holds current item).
+            /// <summary>
+            /// Move enumerator to next item in tree, or the first item if
+            /// this is the first call to MoveNext. 
+            /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+            /// </summary>
+            /// <returns>True if enumerator is valid now</returns>
+            public bool MoveNext()
+            {
+                tree.modifycheck(stamp);
+                if (cursor.right != null)
+                {
+                    path[level] = cursor = cursor.right;
+                    while (cursor.left != null)
+                        path[++level] = cursor = cursor.left;
+                }
+                else if (level == 0)
+                    return valid = false;
+                else
+                    cursor = path[--level];
+
+                current = cursor.item;
+                return valid = true;
+            }
+
+
+            #region IDisposable Members for Enumerator
+
+            bool disposed;
+
+
+            /// <summary>
+            /// Call Dispose(true) and then suppress finalization of this enumerator.
+            /// </summary>
+            public void Dispose()
+            {
+                Dispose(true);
+                GC.SuppressFinalize(this);
+            }
+
+
+            /// <summary>
+            /// Remove the internal data (notably the stack array).
+            /// </summary>
+            /// <param name="disposing">True if called from Dispose(),
+            /// false if called from the finalizer</param>
+            protected virtual void Dispose(bool disposing)
+            {
+                if (!disposed)
+                {
+                    if (disposing)
+                    {
+                    }
+
+                    current = default(T);
+                    cursor = null;
+                    path = null;
+                    disposed = true;
+                }
+            }
+
+
+            /// <summary>
+            /// Finalizer for enumerator
+            /// </summary>
+            ~Enumerator()
+            {
+                Dispose(false);
+            }
+            #endregion
+
+
+            #region IEnumerator Members
+
+            object System.Collections.IEnumerator.Current
+            {
+                get { return Current; }
+            }
+
+            bool System.Collections.IEnumerator.MoveNext()
+            {
+                return MoveNext();
+            }
+
+            void System.Collections.IEnumerator.Reset()
+            {
+                throw new NotImplementedException();
+            }
+
+            #endregion
+        }
+
+        /// <summary>
+        /// An enumerator for a snapshot of a node copy persistent red-black tree
+        /// collection.
+        /// </summary>
+        [Serializable]
+        internal class SnapEnumerator : SCG.IEnumerator<T>
+        {
+            #region Private Fields
+            TreeSet<T> tree;
+
+            bool valid = false;
+
+            int stamp;
+
+
+            T current;
+
+            Node cursor;
+
+            Node[] path; // stack of nodes
+
+            int level;
+            #endregion
+
+            /// <summary>
+            /// Create an enumerator for a snapshot of a node copy persistent red-black tree
+            /// collection
+            /// </summary>
+            /// <param name="tree">The snapshot</param>
+            public SnapEnumerator(TreeSet<T> tree)
+            {
+                this.tree = tree;
+                stamp = tree.stamp;
+                path = new Node[2 * tree.blackdepth];
+                cursor = new Node();
+                cursor.right = tree.root;
+            }
+
+
+            #region SCG.IEnumerator<T> Members
+
+            /// <summary>
+            /// Move enumerator to next item in tree, or the first item if
+            /// this is the first call to MoveNext. 
+            /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+            /// </summary>
+            /// <returns>True if enumerator is valid now</returns>
+            public bool MoveNext()
+            {
+                tree.modifycheck(stamp);//???
+
+
+                Node next = tree.right(cursor);
+
+                if (next != null)
+                {
+                    path[level] = cursor = next;
+                    next = tree.left(cursor);
+                    while (next != null)
+                    {
+                        path[++level] = cursor = next;
+                        next = tree.left(cursor);
+                    }
+                }
+                else if (level == 0)
+                    return valid = false;
+                else
+                    cursor = path[--level];
+
+
+                current = cursor.item;
+                return valid = true;
+            }
+
+
+            /// <summary>
+            /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+            /// </summary>
+            /// <value>The current value of the enumerator.</value>
+            public T Current
+            {
+                get
+                {
+                    if (valid)
+                        return current;
+                    else
+                        throw new InvalidOperationException();
+                }
+            }
+
+            #endregion
+
+            #region IDisposable Members
+
+            void System.IDisposable.Dispose()
+            {
+                tree = null;
+                valid = false;
+                current = default(T);
+                cursor = null;
+                path = null;
+            }
+
+            #endregion
+
+            #region IEnumerator Members
+
+            object System.Collections.IEnumerator.Current
+            {
+                get { return Current; }
+            }
+
+            bool System.Collections.IEnumerator.MoveNext()
+            {
+                return MoveNext();
+            }
+
+            void System.Collections.IEnumerator.Reset()
+            {
+                throw new NotImplementedException();
+            }
+
+            #endregion
+        }
+
+        #endregion
+
+        #region IEnumerable<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="NoSuchItemException">If tree is empty</exception>
+        /// <returns></returns>
+        public override T Choose()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+
+            if (size == 0)
+                throw new NoSuchItemException();
+            return root.item;
+        }
+
+
+        /// <summary>
+        /// Create an enumerator for this tree
+        /// </summary>
+        /// <returns>The enumerator</returns>
+        public override SCG.IEnumerator<T> GetEnumerator()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+
+            if (isSnapShot)
+                return new SnapEnumerator(this);
+
+            return new Enumerator(this);
+
+        }
+
+        #endregion
+
+        #region ISink<T> Members
+
+        /// <summary>
+        /// Add item to tree. If already there, return the found item in the second argument.
+        /// </summary>
+        /// <param name="item">Item to add</param>
+        /// <param name="founditem">item found</param>
+        /// <param name="update">whether item in node should be updated</param>
+        /// <param name="wasfound">true if found in bag, false if not found or tree is a set</param>
+        /// <returns>True if item was added</returns>
+        bool addIterative(T item, ref T founditem, bool update, out bool wasfound)
+        {
+            wasfound = false;
+            if (root == null)
+            {
+                root = new Node();
+                root.red = false;
+                blackdepth = 1;
+                root.item = item;
+                root.generation = generation;
+                return true;
+            }
+
+            stackcheck();
+
+            int level = 0;
+            Node cursor = root;
+
+            while (true)
+            {
+                int comp = comparer.Compare(cursor.item, item);
+
+                if (comp == 0)
+                {
+                    founditem = cursor.item;
+
+                    bool nodeWasUpdated = update;
+                    if (update)
+                    {
+                        Node.CopyNode(ref cursor, maxsnapid, generation);
+                        cursor.item = item;
+                    }
+
+
+                    while (level-- > 0)
+                    {
+                        if (nodeWasUpdated)
+                        {
+                            Node kid = cursor;
+
+                            cursor = path[level];
+                            Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+
+                        }
+
+                        path[level] = null;
+                    }
+
+                    if (update)
+                        root = cursor;
+
+                    return false;
+
+                }
+
+                //else
+                Node child = comp > 0 ? cursor.left : cursor.right;
+
+                if (child == null)
+                {
+                    child = new Node();
+                    child.item = item;
+                    child.generation = generation;
+                    Node.update(ref cursor, comp > 0, child, maxsnapid, generation);
+
+                    cursor.size++;
+
+                    dirs[level] = comp;
+                    break;
+                }
+                else
+                {
+                    dirs[level] = comp;
+                    path[level++] = cursor;
+                    cursor = child;
+                }
+            }
+
+            //We have just added the red node child to "cursor"
+            while (cursor.red)
+            {
+                //take one step up:
+                Node child = cursor;
+
+                cursor = path[--level];
+                path[level] = null;
+                Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+                cursor.size++;
+                int comp = dirs[level];
+                Node childsibling = comp > 0 ? cursor.right : cursor.left;
+
+                if (childsibling != null && childsibling.red)
+                {
+                    //Promote
+                    child.red = false;
+                    Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);
+                    childsibling.red = false;
+
+                    //color cursor red & take one step up the tree unless at root
+                    if (level == 0)
+                    {
+                        root = cursor;
+                        blackdepth++;
+                        return true;
+                    }
+                    else
+                    {
+                        cursor.red = true;
+                        child = cursor;
+                        cursor = path[--level];
+                        Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+                        path[level] = null;
+                        cursor.size++;
+                    }
+                }
+                else
+                {
+                    //ROTATE!!!
+                    int childcomp = dirs[level + 1];
+
+                    cursor.red = true;
+                    if (comp > 0)
+                    {
+                        if (childcomp > 0)
+                        {//zagzag
+                            Node.update(ref cursor, true, child.right, maxsnapid, generation);
+                            Node.update(ref child, false, cursor, maxsnapid, generation);
+
+                            cursor = child;
+                        }
+                        else
+                        {//zagzig
+                            Node badgrandchild = child.right;
+                            Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);
+                            Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);
+                            Node.CopyNode(ref badgrandchild, maxsnapid, generation);
+
+                            badgrandchild.left = child;
+                            badgrandchild.right = cursor;
+                            cursor = badgrandchild;
+                        }
+                    }
+                    else
+                    {//comp < 0
+                        if (childcomp < 0)
+                        {//zigzig
+                            Node.update(ref cursor, false, child.left, maxsnapid, generation);
+                            Node.update(ref child, true, cursor, maxsnapid, generation);
+
+                            cursor = child;
+                        }
+                        else
+                        {//zigzag
+                            Node badgrandchild = child.left;
+                            Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);
+                            Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);
+                            Node.CopyNode(ref badgrandchild, maxsnapid, generation);
+
+                            badgrandchild.right = child;
+                            badgrandchild.left = cursor;
+                            cursor = badgrandchild;
+                        }
+                    }
+
+                    cursor.red = false;
+
+                    Node n;
+
+
+                    n = cursor.right;
+                    cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+                    n = cursor.left;
+                    n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+                    cursor.size += n.size + 1;
+
+                    if (level == 0)
+                    {
+                        root = cursor;
+                        return true;
+                    }
+                    else
+                    {
+                        child = cursor;
+                        cursor = path[--level];
+                        path[level] = null;
+                        Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+
+                        cursor.size++;
+                        break;
+                    }
+                }
+            }
+            bool stillmore = true;
+            while (level > 0)
+            {
+                Node child = cursor;
+
+                cursor = path[--level];
+                path[level] = null;
+                if (stillmore)
+                    stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+                cursor.size++;
+            }
+
+            root = cursor;
+            return true;
+        }
+
+
+        /// <summary>
+        /// Add an item to this collection if possible. If this collection has set
+        /// semantics, the item will be added if not already in the collection. If
+        /// bag semantics, the item will always be added.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
+        /// <returns>True if item was added.</returns>
+        public bool Add(T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+
+            //Note: blackdepth of the tree is set inside addIterative
+            T jtem = default(T);
+            if (!add(item, ref jtem))
+                return false;
+            if (ActiveEvents != 0)
+                raiseForAdd(jtem);
+            return true;
+        }
+
+        /// <summary>
+        /// Add an item to this collection if possible. If this collection has set
+        /// semantics, the item will be added if not already in the collection. If
+        /// bag semantics, the item will always be added.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
+        void SCG.ICollection<T>.Add(T item)
+        {
+            Add(item);
+        }
+
+        private bool add(T item, ref T j)
+        {
+            bool wasFound;
+
+            if (addIterative(item, ref j, false, out wasFound))
+            {
+                size++;
+                if (!wasFound)
+                    j = item;
+                return true;
+            }
+            else
+                return false;
+        }
+
+        /// <summary>
+        /// Add the elements from another collection with a more specialized item type 
+        /// to this collection. If this
+        /// collection has set semantics, only items not already in the collection
+        /// will be added.
+        /// </summary>
+        /// <param name="items">The items to add</param>
+        public void AddAll(SCG.IEnumerable<T> items)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+
+            int c = 0;
+            T j = default(T);
+            bool tmp;
+
+            bool raiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;
+            CircularQueue<T> wasAdded = raiseAdded ? new CircularQueue<T>() : null;
+
+            foreach (T i in items)
+                if (addIterative(i, ref j, false, out tmp))
+                {
+                    c++;
+                    if (raiseAdded)
+                        wasAdded.Enqueue(tmp ? j : i);
+                }
+            if (c == 0)
+                return;
+
+            size += c;
+            //TODO: implement a RaiseForAddAll() method
+            if (raiseAdded)
+                foreach (T item in wasAdded)
+                    raiseItemsAdded(item, 1);
+            if (((ActiveEvents & EventTypeEnum.Changed) != 0))
+                raiseCollectionChanged();
+        }
+
+
+        /// <summary>
+        /// Add all the items from another collection with an enumeration order that 
+        /// is increasing in the items. <para>The idea is that the implementation may use
+        /// a faster algorithm to merge the two collections.</para>
+        /// <exception cref="ArgumentException"/> if the enumerated items turns out
+        /// not to be in increasing order.
+        /// </summary>
+        /// <param name="items">The collection to add.</param>
+        public void AddSorted(SCG.IEnumerable<T> items)
+        {
+            if (size > 0)
+                AddAll(items);
+            else
+            {
+                if (!isValid)
+                    throw new ViewDisposedException("Snapshot has been disposed");
+                updatecheck();
+                addSorted(items, true, true);
+            }
+        }
+
+        #region add-sorted helpers
+
+        //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a
+        //singly linked list of red nodes using only the right child refs.
+        //The x nodes at depth h+1 will be red, the rest black.
+        //(h is the blackdepth of the resulting tree)
+        static Node maketreer(ref Node rest, int blackheight, int maxred, int red)
+        {
+            if (blackheight == 1)
+            {
+                Node top = rest;
+
+                rest = rest.right;
+                if (red > 0)
+                {
+                    top.right = null;
+                    rest.left = top;
+                    top = rest;
+                    top.size = 1 + red;
+                    rest = rest.right;
+                    red--;
+                }
+
+                if (red > 0)
+                {
+
+                    top.right = rest;
+                    rest = rest.right;
+                    top.right.right = null;
+                }
+                else
+                    top.right = null;
+
+                top.red = false;
+                return top;
+            }
+            else
+            {
+                maxred >>= 1;
+
+                int lred = red > maxred ? maxred : red;
+                Node left = maketreer(ref rest, blackheight - 1, maxred, lred);
+                Node top = rest;
+
+                rest = rest.right;
+                top.left = left;
+                top.red = false;
+                top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);
+                top.size = (maxred << 1) - 1 + red;
+                return top;
+            }
+        }
+
+
+        void addSorted(SCG.IEnumerable<T> items, bool safe, bool raise)
+        {
+            SCG.IEnumerator<T> e = items.GetEnumerator(); ;
+            if (size > 0)
+                throw new InternalException("This can't happen");
+
+            if (!e.MoveNext())
+                return;
+
+            //To count theCollect 
+            Node head = new Node(), tail = head;
+            int z = 1;
+            T lastitem = tail.item = e.Current;
+
+
+            while (e.MoveNext())
+            {
+
+                z++;
+                tail.right = new Node();
+                tail = tail.right;
+                tail.item = e.Current;
+                if (safe)
+                {
+                    if (comparer.Compare(lastitem, tail.item) >= 0)
+                        throw new ArgumentException("Argument not sorted");
+
+                    lastitem = tail.item;
+                }
+                tail.generation = generation;
+
+            }
+
+            int blackheight = 0, red = z, maxred = 1;
+
+            while (maxred <= red)
+            {
+                red -= maxred;
+                maxred <<= 1;
+                blackheight++;
+            }
+
+            root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);
+            blackdepth = blackheight;
+            size = z;
+
+
+            if (raise)
+            {
+                if ((ActiveEvents & EventTypeEnum.Added) != 0)
+                {
+                    CircularQueue<T> wasAdded = new CircularQueue<T>();
+                    foreach (T item in this)
+                        wasAdded.Enqueue(item);
+                    foreach (T item in wasAdded)
+                        raiseItemsAdded(item, 1);
+                }
+                if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                    raiseCollectionChanged();
+            }
+            return;
+        }
+
+        #endregion
+
+
+        /// <summary></summary>
+        /// <value>False since this tree has set semantics.</value>
+        public bool AllowsDuplicates { get { return false; } }
+
+        /// <summary>
+        /// By convention this is true for any collection with set semantics.
+        /// </summary>
+        /// <value>True if only one representative of a group of equal items 
+        /// is kept in the collection together with the total count.</value>
+        public virtual bool DuplicatesByCounting { get { return true; } }
+
+        #endregion
+
+        #region IEditableCollection<T> Members
+
+
+        /// <summary>
+        /// The value is symbolic indicating the type of asymptotic complexity
+        /// in terms of the size of this collection (worst-case or amortized as
+        /// relevant).
+        /// </summary>
+        /// <value>Speed.Log</value>
+        public Speed ContainsSpeed { get { return Speed.Log; } }
+
+        /// <summary>
+        /// Check if this collection contains (an item equivalent to according to the
+        /// itemequalityComparer) a particular value.
+        /// </summary>
+        /// <param name="item">The value to check for.</param>
+        /// <returns>True if the items is in this collection.</returns>
+        public bool Contains(T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            Node next; int comp = 0;
+
+            next = root;
+            while (next != null)
+            {
+                comp = comparer.Compare(next.item, item);
+                if (comp == 0)
+                    return true;
+
+                next = comp < 0 ? right(next) : left(next);
+            }
+
+            return false;
+        }
+
+
+        //Variant for dictionary use
+        //Will return the actual matching item in the ref argument.
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+        /// binary copy of) the actual value found.
+        /// </summary>
+        /// <param name="item">The value to look for.</param>
+        /// <returns>True if the items is in this collection.</returns>
+        public bool Find(ref T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            Node next; int comp = 0;
+
+            next = root;
+            while (next != null)
+            {
+                comp = comparer.Compare(next.item, item);
+                if (comp == 0)
+                {
+                    item = next.item;
+                    return true;
+                }
+
+                next = comp < 0 ? right(next) : left(next);
+            }
+
+            return false;
+        }
+
+
+        /// <summary>
+        /// Find or add the item to the tree. If the tree does not contain
+        /// an item equivalent to this item add it, else return the existing
+        /// one in the ref argument. 
+        ///
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns>True if item was found</returns>
+        public bool FindOrAdd(ref T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            bool wasfound;
+
+            //Note: blackdepth of the tree is set inside addIterative
+            if (addIterative(item, ref item, false, out wasfound))
+            {
+                size++;
+                if (ActiveEvents != 0 && !wasfound)
+                    raiseForAdd(item);
+                return wasfound;
+            }
+            else
+                return true;
+
+        }
+
+
+        //For dictionary use. 
+        //If found, the matching entry will be updated with the new item.
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, update the item in the collection 
+        /// to with a binary copy of the supplied value. If the collection has bag semantics,
+        /// this updates all equivalent copies in
+        /// the collection.
+        /// </summary>
+        /// <param name="item">Value to update.</param>
+        /// <returns>True if the item was found and hence updated.</returns>
+        public bool Update(T item)
+        {
+            T olditem = item;
+            return Update(item, out olditem);
+        }
+
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, update the item in the collection 
+        /// with a binary copy of the supplied value. If the collection has bag semantics,
+        /// this updates all equivalent copies in
+        /// the collection.
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public bool Update(T item, out T olditem)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            stackcheck();
+
+            int level = 0;
+            Node cursor = root;
+            int comp = 0;
+
+            while (cursor != null)
+            {
+                comp = comparer.Compare(cursor.item, item);
+                if (comp == 0)
+                {
+                    Node.CopyNode(ref cursor, maxsnapid, generation);
+                    olditem = cursor.item;
+
+                    cursor.item = item;
+                    while (level > 0)
+                    {
+                        Node child = cursor;
+
+                        cursor = path[--level];
+                        path[level] = null;
+                        Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+
+                    }
+
+                    root = cursor;
+
+                    if (ActiveEvents != 0)
+                        raiseForUpdate(item, olditem);
+
+                    return true;
+                }
+                dirs[level] = comp;
+                path[level++] = cursor;
+                cursor = comp < 0 ? cursor.right : cursor.left;
+            }
+
+            olditem = default(T);
+            return false;
+        }
+
+
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, update the item in the collection 
+        /// with a binary copy of the supplied value; else add the value to the collection. 
+        ///
+        /// <i>NOTE: the bag implementation is currently wrong! ?????</i>
+        /// </summary>
+        /// <param name="item">Value to add or update.</param>
+        /// <returns>True if the item was found and updated (hence not added).</returns>
+        public bool UpdateOrAdd(T item)
+        { T olditem; return UpdateOrAdd(item, out olditem); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public bool UpdateOrAdd(T item, out T olditem)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            bool wasfound;
+            olditem = default(T);
+
+
+            //Note: blackdepth of the tree is set inside addIterative
+            if (addIterative(item, ref olditem, true, out wasfound))
+            {
+                size++;
+                if (ActiveEvents != 0)
+                    raiseForAdd(wasfound ? olditem : item);
+                return wasfound;
+            }
+            else
+            {
+                if (ActiveEvents != 0)
+                    raiseForUpdate(item, olditem, 1);
+                return true;
+            }
+        }
+
+
+        /// <summary>
+        /// Remove a particular item from this collection. If the collection has bag
+        /// semantics only one copy equivalent to the supplied item is removed. 
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        /// <returns>True if the item was found (and removed).</returns>
+        public bool Remove(T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            if (root == null)
+                return false;
+
+            int junk;
+            bool retval = removeIterative(ref item, false, out junk);
+            if (ActiveEvents != 0 && retval)
+                raiseForRemove(item);
+            return retval;
+        }
+
+        /// <summary>
+        /// Remove a particular item from this collection if found. If the collection
+        /// has bag semantics only one copy equivalent to the supplied item is removed,
+        /// which one is implementation dependent. 
+        /// If an item was removed, report a binary copy of the actual item removed in 
+        /// the argument.
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        /// <param name="removeditem">The removed value.</param>
+        /// <returns>True if the item was found (and removed).</returns>
+        public bool Remove(T item, out T removeditem)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            removeditem = item;
+            if (root == null)
+                return false;
+
+            int junk;
+            bool retval = removeIterative(ref removeditem, false, out junk);
+            if (ActiveEvents != 0 && retval)
+                raiseForRemove(item);
+            return retval;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item">input: item to remove; output: item actually removed</param>
+        /// <param name="all">If true, remove all copies</param>
+        /// <param name="wasRemoved"></param>
+        /// <returns></returns>
+        private bool removeIterative(ref T item, bool all, out int wasRemoved)
+        {
+            wasRemoved = 0;
+            //Stage 1: find item
+            stackcheck();
+
+            int level = 0, comp;
+            Node cursor = root;
+
+            while (true)
+            {
+                comp = comparer.Compare(cursor.item, item);
+                if (comp == 0)
+                {
+                    item = cursor.item;
+
+                    wasRemoved = 1;
+
+                    break;
+                }
+
+                Node child = comp > 0 ? cursor.left : cursor.right;
+
+                if (child == null)
+                    return false;
+
+                dirs[level] = comp;
+                path[level++] = cursor;
+                cursor = child;
+            }
+
+            return removeIterativePhase2(cursor, level);
+        }
+
+
+        private bool removeIterativePhase2(Node cursor, int level)
+        {
+            if (size == 1)
+            {
+                clear();
+                return true;
+            }
+
+
+            //We are certain to remove one node:
+            size--;
+
+            //Stage 2: if item's node has no null child, find predecessor
+            int level_of_item = level;
+
+            if (cursor.left != null && cursor.right != null)
+            {
+                dirs[level] = 1;
+                path[level++] = cursor;
+                cursor = cursor.left;
+                while (cursor.right != null)
+                {
+                    dirs[level] = -1;
+                    path[level++] = cursor;
+                    cursor = cursor.right;
+                }
+                Node.CopyNode(ref path[level_of_item], maxsnapid, generation);
+                path[level_of_item].item = cursor.item;
+
+            }
+
+            //Stage 3: splice out node to be removed
+            Node newchild = cursor.right == null ? cursor.left : cursor.right;
+            bool demote_or_rotate = newchild == null && !cursor.red;
+
+            //assert newchild.red 
+            if (newchild != null)
+            {
+                newchild.red = false;
+            }
+
+            if (level == 0)
+            {
+                root = newchild;
+                return true;
+            }
+
+            level--;
+            cursor = path[level];
+            path[level] = null;
+
+            int comp = dirs[level];
+            Node childsibling;
+            Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);
+
+            childsibling = comp > 0 ? cursor.right : cursor.left;
+            cursor.size--;
+
+            //Stage 4: demote till we must rotate
+            Node farnephew = null, nearnephew = null;
+
+            while (demote_or_rotate)
+            {
+                if (childsibling.red)
+                    break; //rotate 2+?
+
+                farnephew = comp > 0 ? childsibling.right : childsibling.left;
+                if (farnephew != null && farnephew.red)
+                    break; //rotate 1b
+
+                nearnephew = comp > 0 ? childsibling.left : childsibling.right;
+                if (nearnephew != null && nearnephew.red)
+                    break; //rotate 1c
+
+                //demote cursor
+                childsibling.red = true;
+                if (level == 0)
+                {
+                    cursor.red = false;
+                    blackdepth--;
+                    root = cursor;
+                    return true;
+                }
+                else if (cursor.red)
+                {
+                    cursor.red = false;
+                    demote_or_rotate = false;
+                    break; //No rotation
+                }
+                else
+                {
+                    Node child = cursor;
+
+                    cursor = path[--level];
+                    path[level] = null;
+                    comp = dirs[level];
+                    childsibling = comp > 0 ? cursor.right : cursor.left;
+                    Node.update(ref cursor, comp > 0, child, maxsnapid, generation);
+                    cursor.size--;
+                }
+            }
+
+            //Stage 5: rotate 
+            if (demote_or_rotate)
+            {
+                //At start:
+                //parent = cursor (temporary for swapping nodes)
+                //childsibling is the sibling of the updated child (x)
+                //cursor is always the top of the subtree
+                Node parent = cursor;
+
+                if (childsibling.red)
+                {//Case 2 and perhaps more. 
+                    //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null 
+                    //(and black). The grandnephews are children of nearnephew
+                    Node neargrandnephew, fargrandnephew;
+
+                    if (comp > 0)
+                    {
+                        nearnephew = childsibling.left;
+                        farnephew = childsibling.right;
+                        neargrandnephew = nearnephew.left;
+                        fargrandnephew = nearnephew.right;
+                    }
+                    else
+                    {
+                        nearnephew = childsibling.right;
+                        farnephew = childsibling.left;
+                        neargrandnephew = nearnephew.right;
+                        fargrandnephew = nearnephew.left;
+                    }
+
+                    if (fargrandnephew != null && fargrandnephew.red)
+                    {//Case 2+1b
+                        Node.CopyNode(ref nearnephew, maxsnapid, generation);
+
+                        //The end result of this will always be e copy of parent
+                        Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);
+                        Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);
+                        if (comp > 0)
+                        {
+                            nearnephew.left = parent;
+                            parent.right = neargrandnephew;
+                        }
+                        else
+                        {
+                            nearnephew.right = parent;
+                            parent.left = neargrandnephew;
+                        }
+
+                        cursor = childsibling;
+                        childsibling.red = false;
+                        nearnephew.red = true;
+                        fargrandnephew.red = false;
+                        cursor.size = parent.size;
+                        nearnephew.size = cursor.size - 1 - farnephew.size;
+                        parent.size = nearnephew.size - 1 - fargrandnephew.size;
+                    }
+                    else if (neargrandnephew != null && neargrandnephew.red)
+                    {//Case 2+1c
+                        Node.CopyNode(ref neargrandnephew, maxsnapid, generation);
+                        if (comp > 0)
+                        {
+                            Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);
+                            Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);
+                            Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);
+                            neargrandnephew.left = parent;
+                            neargrandnephew.right = nearnephew;
+                        }
+                        else
+                        {
+                            Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);
+                            Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);
+                            Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);
+                            neargrandnephew.right = parent;
+                            neargrandnephew.left = nearnephew;
+                        }
+
+                        cursor = childsibling;
+                        childsibling.red = false;
+                        cursor.size = parent.size;
+                        parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+                        nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);
+                        neargrandnephew.size = 1 + parent.size + nearnephew.size;
+                    }
+                    else
+                    {//Case 2 only
+                        Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);
+                        Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);
+
+                        cursor = childsibling;
+                        childsibling.red = false;
+                        nearnephew.red = true;
+                        cursor.size = parent.size;
+                        parent.size -= farnephew.size + 1;
+                    }
+                }
+                else if (farnephew != null && farnephew.red)
+                {//Case 1b
+                    nearnephew = comp > 0 ? childsibling.left : childsibling.right;
+                    Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);
+                    Node.CopyNode(ref childsibling, maxsnapid, generation);
+                    if (comp > 0)
+                    {
+                        childsibling.left = parent;
+                        childsibling.right = farnephew;
+                    }
+                    else
+                    {
+                        childsibling.right = parent;
+                        childsibling.left = farnephew;
+                    }
+
+                    cursor = childsibling;
+                    cursor.red = parent.red;
+                    parent.red = false;
+                    farnephew.red = false;
+
+                    cursor.size = parent.size;
+                    parent.size -= farnephew.size + 1;
+                }
+                else if (nearnephew != null && nearnephew.red)
+                {//Case 1c
+                    Node.CopyNode(ref nearnephew, maxsnapid, generation);
+                    if (comp > 0)
+                    {
+                        Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);
+                        Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);
+
+                        nearnephew.left = parent;
+                        nearnephew.right = childsibling;
+                    }
+                    else
+                    {
+                        Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);
+                        Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);
+
+                        nearnephew.right = parent;
+                        nearnephew.left = childsibling;
+                    }
+
+                    cursor = nearnephew;
+                    cursor.red = parent.red;
+                    parent.red = false;
+                    cursor.size = parent.size;
+                    parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+                    childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);
+                }
+                else
+                {//Case 1a can't happen
+                    throw new InternalException("Case 1a can't happen here");
+                }
+
+                //Resplice cursor:
+                if (level == 0)
+                {
+                    root = cursor;
+                }
+                else
+                {
+                    Node swap = cursor;
+
+                    cursor = path[--level];
+                    path[level] = null;
+                    Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);
+
+                    cursor.size--;
+                }
+            }
+
+            //Stage 6: fixup to the root
+            while (level > 0)
+            {
+                Node child = cursor;
+
+                cursor = path[--level];
+                path[level] = null;
+                if (child != (dirs[level] > 0 ? cursor.left : cursor.right))
+                    Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+
+                cursor.size--;
+            }
+
+            root = cursor;
+            return true;
+        }
+
+
+        /// <summary>
+        /// Remove all items from this collection.
+        /// </summary>
+        public void Clear()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            if (size == 0)
+                return;
+            int oldsize = size;
+            clear();
+            if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+                raiseCollectionCleared(true, oldsize);
+            if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                raiseCollectionChanged();
+        }
+
+
+        private void clear()
+        {
+            size = 0;
+            root = null;
+            blackdepth = 0;
+        }
+
+
+        /// <summary>
+        /// Remove all items in another collection from this one. If this collection
+        /// has bag semantics, take multiplicities into account.
+        /// </summary>
+        /// <param name="items">The items to remove.</param>
+        public void RemoveAll(SCG.IEnumerable<T> items)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+
+            T jtem;
+
+            bool mustRaise = (ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;
+            RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;
+
+            foreach (T item in items)
+            {
+                if (root == null)
+                    break;
+
+                jtem = item;
+                int junk;
+                if (removeIterative(ref jtem, false, out junk) && mustRaise)
+                    raiseHandler.Remove(jtem);
+            }
+            if (mustRaise)
+                raiseHandler.Raise();
+        }
+
+        /// <summary>
+        /// Remove all items not in some other collection from this one. If this collection
+        /// has bag semantics, take multiplicities into account.
+        /// </summary>
+        /// <param name="items">The items to retain.</param>
+        public void RetainAll(SCG.IEnumerable<T> items)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+
+            //A much more efficient version is possible if items is sorted like this.
+            //Well, it is unclear how efficient it would be.
+            //We could use a marking method!?
+#warning how does this work together with persistence?
+            TreeSet<T> t = (TreeSet<T>)MemberwiseClone();
+
+            T jtem = default(T);
+            t.clear();
+            foreach (T item in items)
+                if (ContainsCount(item) > t.ContainsCount(item))
+                {
+                    t.add(item, ref jtem);
+                }
+            if (size == t.size)
+                return;
+
+#warning improve (mainly for bag) by using a Node iterator instead of ItemMultiplicities()
+            CircularQueue<KeyValuePair<T, int>> wasRemoved = null;
+            if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+            {
+                wasRemoved = new CircularQueue<KeyValuePair<T, int>>();
+                SCG.IEnumerator<KeyValuePair<T, int>> ie = ItemMultiplicities().GetEnumerator();
+                foreach (KeyValuePair<T, int> p in t.ItemMultiplicities())
+                {
+                    //We know p.Key is in this!
+                    while (ie.MoveNext())
+                    {
+                        if (comparer.Compare(ie.Current.Key, p.Key) == 0)
+                        {
+
+                            break;
+                        }
+                        else
+                            wasRemoved.Enqueue(ie.Current);
+                    }
+                }
+                while (ie.MoveNext())
+                    wasRemoved.Enqueue(ie.Current);
+            }
+
+            root = t.root;
+            size = t.size;
+            blackdepth = t.blackdepth;
+            if (wasRemoved != null)
+                foreach (KeyValuePair<T, int> p in wasRemoved)
+                    raiseItemsRemoved(p.Key, p.Value);
+            if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                raiseCollectionChanged();
+        }
+
+        /// <summary>
+        /// Check if this collection contains all the values in another collection.
+        /// If this collection has bag semantics (<code>AllowsDuplicates==true</code>)
+        /// the check is made with respect to multiplicities, else multiplicities
+        /// are not taken into account.
+        /// </summary>
+        /// <param name="items">The </param>
+        /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+        public bool ContainsAll(SCG.IEnumerable<T> items)
+        {
+            //TODO: fix bag implementation
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            //This is worst-case O(m*logn)
+            foreach (T item in items)
+                if (!Contains(item)) return false;
+
+            return true;
+        }
+
+
+        //Higher order:
+        /// <summary>
+        /// Create a new indexed sorted collection consisting of the items of this
+        /// indexed sorted collection satisfying a certain predicate.
+        /// </summary>
+        /// <param name="filter">The filter delegate defining the predicate.</param>
+        /// <returns>The new indexed sorted collection.</returns>
+        public IIndexedSorted<T> FindAll(Func<T, bool> filter)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            TreeSet<T> res = new TreeSet<T>(comparer);
+            SCG.IEnumerator<T> e = GetEnumerator();
+            Node head = null, tail = null;
+            int z = 0;
+
+            while (e.MoveNext())
+            {
+                T thisitem = e.Current;
+
+                if (filter(thisitem))
+                {
+                    if (head == null)
+                    {
+                        head = tail = new Node();
+                    }
+                    else
+                    {
+
+                        tail.right = new Node();
+                        tail = tail.right;
+                    }
+
+                    tail.item = thisitem;
+                    z++;
+                }
+            }
+
+
+            if (z == 0)
+                return res;
+
+            int blackheight = 0, red = z, maxred = 1;
+
+            while (maxred <= red)
+            {
+                red -= maxred;
+                maxred <<= 1;
+                blackheight++;
+            }
+
+            res.root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);
+            res.blackdepth = blackheight;
+            res.size = z;
+
+            return res;
+        }
+
+
+        /// <summary>
+        /// Create a new indexed sorted collection consisting of the results of
+        /// mapping all items of this list.
+        /// <exception cref="ArgumentException"/> if the map is not increasing over 
+        /// the items of this collection (with respect to the two given comparison 
+        /// relations).
+        /// </summary>
+        /// <param name="mapper">The delegate definging the map.</param>
+        /// <param name="c">The comparion relation to use for the result.</param>
+        /// <returns>The new sorted collection.</returns>
+        public IIndexedSorted<V> Map<V>(Func<T, V> mapper, SCG.IComparer<V> c)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            TreeSet<V> res = new TreeSet<V>(c);
+
+            if (size == 0)
+                return res;
+
+            SCG.IEnumerator<T> e = GetEnumerator();
+            TreeSet<V>.Node head = null, tail = null;
+            V oldv = default(V);
+            int z = 0;
+
+            while (e.MoveNext())
+            {
+                T thisitem = e.Current;
+
+                V newv = mapper(thisitem);
+
+                if (head == null)
+                {
+                    head = tail = new TreeSet<V>.Node();
+                    z++;
+                }
+                else
+                {
+                    int comp = c.Compare(oldv, newv);
+
+                    if (comp >= 0)
+
+                        throw new ArgumentException("mapper not monotonic");
+
+                    tail.right = new TreeSet<V>.Node();
+                    tail = tail.right;
+                    z++;
+                }
+
+                tail.item = oldv = newv;
+            }
+
+
+            int blackheight = 0, red = z, maxred = 1;
+
+            while (maxred <= red)
+            {
+                red -= maxred;
+                maxred <<= 1;
+                blackheight++;
+            }
+
+            res.root = TreeSet<V>.maketreer(ref head, blackheight, maxred, red);
+            res.blackdepth = blackheight;
+            res.size = size;
+            return res;
+        }
+
+
+        //below is the bag utility stuff
+        /// <summary>
+        /// Count the number of items of the collection equal to a particular value.
+        /// Returns 0 if and only if the value is not in the collection.
+        /// </summary>
+        /// <param name="item">The value to count.</param>
+        /// <returns>The number of copies found.</returns>
+        public int ContainsCount(T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+
+            //Since we are strictly not AllowsDuplicates we just do
+            return Contains(item) ? 1 : 0;
+
+        }
+
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<T> UniqueItems()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+
+            return this;
+
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+
+            return new MultiplicityOne<T>(this);
+
+        }
+
+        /// <summary>
+        /// Remove all items equivalent to a given value.
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        public void RemoveAllCopies(T item)
+        {
+
+            Remove(item);
+
+        }
+
+
+        #endregion
+
+        #region IIndexed<T> Members
+
+        private Node findNode(int i)
+        {
+            if (isSnapShot)
+                throw new NotSupportedException("Indexing not supported for snapshots");
+            Node next = root;
+
+            if (i >= 0 && i < size)
+                while (true)
+                {
+                    int j = next.left == null ? 0 : next.left.size;
+
+                    if (i > j)
+                    {
+
+                        i -= j + 1;
+
+                        next = next.right;
+                    }
+                    else if (i == j)
+                        return next;
+                    else
+                        next = next.left;
+                }
+
+            throw new IndexOutOfRangeException();
+
+        }
+
+
+        /// <summary>
+        /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+        /// &gt;= the size of the collection.
+        /// </summary>
+        /// <value>The i'th item of this list.</value>
+        /// <param name="i">the index to lookup</param>
+        public T this[int i] { get { return findNode(i).item; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual Speed IndexingSpeed { get { return Speed.Log; } }
+
+
+        //TODO: return -upper instead of -1 in case of not found
+        /// <summary>
+        /// Searches for an item in this indexed collection going forwards from the start.
+        /// </summary>
+        /// <param name="item">Item to search for.</param>
+        /// <returns>Index of first occurrence from start of the item
+        /// if found, else the two-complement 
+        /// (always negative) of the index at which the item would be put if it was added.</returns>
+        public int IndexOf(T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            int upper;
+            return indexOf(item, out upper);
+        }
+
+
+        private int indexOf(T item, out int upper)
+        {
+            if (isSnapShot)
+                throw new NotSupportedException("Indexing not supported for snapshots");
+            int ind = 0; Node next = root;
+
+            while (next != null)
+            {
+                int comp = comparer.Compare(item, next.item);
+
+                if (comp < 0)
+                    next = next.left;
+                else
+                {
+                    int leftcnt = next.left == null ? 0 : next.left.size;
+
+                    if (comp == 0)
+                    {
+
+                        return upper = ind + leftcnt;
+
+                    }
+                    else
+                    {
+
+                        ind = ind + 1 + leftcnt;
+
+                        next = next.right;
+                    }
+                }
+            }
+            upper = ~ind;
+            return ~ind;
+        }
+
+
+        /// <summary>
+        /// Searches for an item in the tree going backwards from the end.
+        /// </summary>
+        /// <param name="item">Item to search for.</param>
+        /// <returns>Index of last occurrence from the end of item if found, 
+        /// else the two-complement (always negative) of the index at which 
+        /// the item would be put if it was added.</returns>
+        public int LastIndexOf(T item)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+
+            //We have AllowsDuplicates==false for the set
+            return IndexOf(item);
+
+        }
+
+
+        /// <summary>
+        /// Remove the item at a specific position of the list.
+        /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+        /// &gt;= the size of the collection.
+        /// </summary>
+        /// <param name="i">The index of the item to remove.</param>
+        /// <returns>The removed item.</returns>
+        public T RemoveAt(int i)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            T retval = removeAt(i);
+            if (ActiveEvents != 0)
+                raiseForRemove(retval);
+            return retval;
+        }
+
+        T removeAt(int i)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+            if (i < 0 || i >= size)
+                throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue");
+
+            //We must follow the pattern of removeIterative()
+            while (dirs.Length < 2 * blackdepth)
+            {
+                dirs = new int[2 * dirs.Length];
+                path = new Node[2 * dirs.Length];
+            }
+
+            int level = 0;
+            Node cursor = root;
+
+            while (true)
+            {
+                int j = cursor.left == null ? 0 : cursor.left.size;
+
+                if (i > j)
+                {
+
+                    i -= j + 1;
+
+                    dirs[level] = -1;
+                    path[level++] = cursor;
+                    cursor = cursor.right;
+                }
+                else if (i == j)
+                    break;
+                else
+                {
+                    dirs[level] = 1;
+                    path[level++] = cursor;
+                    cursor = cursor.left;
+                }
+            }
+
+            T retval = cursor.item;
+
+
+            removeIterativePhase2(cursor, level);
+            return retval;
+
+        }
+
+
+        /// <summary>
+        /// Remove all items in an index interval.
+        /// <exception cref="IndexOutOfRangeException"/>???. 
+        /// </summary>
+        /// <param name="start">The index of the first item to remove.</param>
+        /// <param name="count">The number of items to remove.</param>
+        public void RemoveInterval(int start, int count)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            if (start < 0 || count < 0 || start + count > this.size)
+                throw new ArgumentOutOfRangeException();
+
+            updatecheck();
+
+            if (count == 0)
+                return;
+
+            //This is terrible for large count. We should split the tree at 
+            //the endpoints of the range and fuse the parts!
+            //We really need good internal destructive split and catenate functions!
+            //Alternative for large counts: rebuild tree using maketree()
+            for (int i = 0; i < count; i++)
+                removeAt(start);
+
+            if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+                raiseCollectionCleared(false, count);
+            if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                raiseCollectionChanged();
+        }
+
+
+        /// <summary>
+        /// <exception cref="IndexOutOfRangeException"/>.
+        /// </summary>
+        /// <value>The directed collection of items in a specific index interval.</value>
+        /// <param name="start">The starting index of the interval (inclusive).</param>
+        /// <param name="count">The length of the interval.</param>
+        public IDirectedCollectionValue<T> this[int start, int count]
+        {
+            get
+            {
+                checkRange(start, count);
+                return new Interval(this, start, count, true);
+            }
+        }
+
+        #region Interval nested class
+        [Serializable]
+        class Interval : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+        {
+            readonly int start, length, stamp;
+
+            readonly bool forwards;
+
+            readonly TreeSet<T> tree;
+
+
+            internal Interval(TreeSet<T> tree, int start, int count, bool forwards)
+            {
+                if (tree.isSnapShot)
+                    throw new NotSupportedException("Indexing not supported for snapshots");
+                this.start = start; this.length = count; this.forwards = forwards;
+                this.tree = tree; this.stamp = tree.stamp;
+            }
+
+            public override bool IsEmpty { get { return length == 0; } }
+
+            public override int Count { get { return length; } }
+
+
+            public override Speed CountSpeed { get { return Speed.Constant; } }
+
+
+            public override T Choose()
+            {
+                if (length == 0)
+                    throw new NoSuchItemException();
+                return tree[start];
+            }
+
+            public override SCG.IEnumerator<T> GetEnumerator()
+            {
+                tree.modifycheck(stamp);
+
+                Node cursor = tree.root;
+                Node[] path = new Node[2 * tree.blackdepth];
+                int level = 0, totaltogo = length;
+
+                if (totaltogo == 0)
+                    yield break;
+
+                if (forwards)
+                {
+                    int i = start;
+
+                    while (true)
+                    {
+                        int j = cursor.left == null ? 0 : cursor.left.size;
+
+                        if (i > j)
+                        {
+
+                            i -= j + 1;
+
+                            cursor = cursor.right;
+                        }
+                        else if (i == j)
+                        {
+
+                            break;
+                        } // i < j, start point tree[start] is in left subtree
+                        else
+                        {
+                            path[level++] = cursor;
+                            cursor = cursor.left;
+                        }
+                    }
+
+                    T current = cursor.item;
+
+                    while (totaltogo-- > 0)
+                    {
+                        yield return current;
+                        tree.modifycheck(stamp);
+
+                        if (cursor.right != null)
+                        {
+                            path[level] = cursor = cursor.right;
+                            while (cursor.left != null)
+                                path[++level] = cursor = cursor.left;
+                        }
+                        else if (level == 0)
+                            yield break;
+                        else
+                            cursor = path[--level];
+
+                        current = cursor.item;
+
+                    }
+                }
+                else // backwards
+                {
+                    int i = start + length - 1;
+
+                    while (true)
+                    {
+                        int j = cursor.left == null ? 0 : cursor.left.size;
+
+                        if (i > j)
+                        {
+
+                            i -= j + 1;
+
+                            path[level++] = cursor;
+                            cursor = cursor.right;
+                        }
+                        else if (i == j)
+                        {
+
+                            break;
+                        }
+                        else // i <= j, end point tree[start+count-1] is in left subtree
+                        {
+                            cursor = cursor.left;
+                        }
+                    }
+
+                    T current = cursor.item;
+
+                    while (totaltogo-- > 0)
+                    {
+                        yield return current;
+                        tree.modifycheck(stamp);
+
+                        if (cursor.left != null)
+                        {
+                            path[level] = cursor = cursor.left;
+                            while (cursor.right != null)
+                                path[++level] = cursor = cursor.right;
+                        }
+                        else if (level == 0)
+                            yield break;
+                        else
+                            cursor = path[--level];
+
+                        current = cursor.item;
+
+                    }
+                }
+
+
+            }
+
+
+            public override IDirectedCollectionValue<T> Backwards()
+            { return new Interval(tree, start, length, !forwards); }
+
+
+            IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()
+            { return Backwards(); }
+
+
+            public override EnumerationDirection Direction
+            {
+                get
+                {
+                    return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;
+                }
+            }
+        }
+        #endregion
+
+        /// <summary>
+        /// Create a collection containing the same items as this collection, but
+        /// whose enumerator will enumerate the items backwards. The new collection
+        /// will become invalid if the original is modified. Method typically used as in
+        /// <code>foreach (T x in coll.Backwards()) {...}</code>
+        /// </summary>
+        /// <returns>The backwards collection.</returns>
+        public override IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }
+
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+        #endregion
+
+        #region PriorityQueue Members
+
+        /// <summary>
+        /// The comparer object supplied at creation time for this collection
+        /// </summary>
+        /// <value>The comparer</value>
+        public SCG.IComparer<T> Comparer { get { return comparer; } }
+
+
+        /// <summary>
+        /// Find the current least item of this priority queue.
+        /// </summary>
+        /// <returns>The least item.</returns>
+        public T FindMin()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            if (size == 0)
+                throw new NoSuchItemException();
+            Node cursor = root, next = left(cursor);
+
+            while (next != null)
+            {
+                cursor = next;
+                next = left(cursor);
+            }
+
+            return cursor.item;
+        }
+
+
+        /// <summary>
+        /// Remove the least item from this  priority queue.
+        /// </summary>
+        /// <returns>The removed item.</returns>
+        public T DeleteMin()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            updatecheck();
+
+            //persistence guard?
+            if (size == 0)
+                throw new NoSuchItemException();
+
+            //We must follow the pattern of removeIterative()
+            stackcheck();
+
+            T retval = deleteMin();
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(retval, 1);
+                raiseCollectionChanged();
+            }
+            return retval;
+        }
+
+        private T deleteMin()
+        {
+            int level = 0;
+            Node cursor = root;
+
+            while (cursor.left != null)
+            {
+                dirs[level] = 1;
+                path[level++] = cursor;
+                cursor = cursor.left;
+            }
+
+            T retval = cursor.item;
+
+            removeIterativePhase2(cursor, level);
+            return retval;
+        }
+
+
+        /// <summary>
+        /// Find the current largest item of this priority queue.
+        /// </summary>
+        /// <returns>The largest item.</returns>
+        public T FindMax()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            if (size == 0)
+                throw new NoSuchItemException();
+
+            Node cursor = root, next = right(cursor);
+
+            while (next != null)
+            {
+                cursor = next;
+                next = right(cursor);
+            }
+
+            return cursor.item;
+        }
+
+
+        /// <summary>
+        /// Remove the largest item from this  priority queue.
+        /// </summary>
+        /// <returns>The removed item.</returns>
+        public T DeleteMax()
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            //persistence guard?
+            updatecheck();
+            if (size == 0)
+                throw new NoSuchItemException();
+
+            //We must follow the pattern of removeIterative()
+            stackcheck();
+
+            T retval = deleteMax();
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(retval, 1);
+                raiseCollectionChanged();
+            }
+            return retval;
+        }
+
+        private T deleteMax()
+        {
+            int level = 0;
+            Node cursor = root;
+
+            while (cursor.right != null)
+            {
+                dirs[level] = -1;
+                path[level++] = cursor;
+                cursor = cursor.right;
+            }
+
+            T retval = cursor.item;
+
+            removeIterativePhase2(cursor, level);
+            return retval;
+        }
+        #endregion
+
+        #region ISorted<T> Members
+
+        /// <summary>
+        /// Find the strict predecessor of item in the sorted collection,
+        /// that is, the greatest item in the collection smaller than the item.
+        /// </summary>
+        /// <param name="item">The item to find the predecessor for.</param>
+        /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+        /// <returns>True if item has a predecessor; otherwise false.</returns>
+        public bool TryPredecessor(T item, out T res)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            Node cursor = root, bestsofar = null;
+
+            while (cursor != null)
+            {
+                int comp = comparer.Compare(cursor.item, item);
+
+                if (comp < 0)
+                {
+                    bestsofar = cursor;
+                    cursor = right(cursor);
+                }
+                else if (comp == 0)
+                {
+                    cursor = left(cursor);
+                    while (cursor != null)
+                    {
+                        bestsofar = cursor;
+                        cursor = right(cursor);
+                    }
+                }
+                else
+                    cursor = left(cursor);
+            }
+            if (bestsofar == null)
+            {
+                res = default(T);
+                return false;
+            }
+            else
+            {
+                res = bestsofar.item;
+                return true;
+            }
+        }
+
+
+        /// <summary>
+        /// Find the strict successor of item in the sorted collection,
+        /// that is, the least item in the collection greater than the supplied value.
+        /// </summary>
+        /// <param name="item">The item to find the successor for.</param>
+        /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+        /// <returns>True if item has a successor; otherwise false.</returns>
+        public bool TrySuccessor(T item, out T res)
+        {
+            if (!isValid)
+                throw new ViewDisposedException("Snapshot has been disposed");
+            Node cursor = root, bestsofar = null;
+
+            while (cursor != null)
+            {
+                int comp = comparer.Compare(cursor.item, item);
+
+                if (comp > 0)
+                {
+                    bestsofar = cursor;
+                    cursor = left(cursor);
+                }
+                else if (comp == 0)
+                {
+                    cursor = right(cursor);
+                    while (cursor != null)
+                    {
+                        bestsofar = cursor;
+                        cursor = left(cursor);
+                    }
+                }
+                else
+                    cursor = right(cursor);
+            }
+
+            if (bestsofar == null)
+            {
+                res = default(T);
+                return false;
+            }
+            else
+            {
+                res = bestsofar.i

<TRUNCATED>

[29/58] [abbrv] lucenenet git commit: WIP on Grouping

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
new file mode 100644
index 0000000..8a01ee0
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
@@ -0,0 +1,943 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Search.Grouping.Terms;
+using Lucene.Net.Index;
+using Lucene.Net.Store;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+
+namespace Lucene.Net.Search.Grouping
+{
+    public class GroupFacetCollectorTest : AbstractGroupingTestCase
+    {
+        [Test]
+        public void TestSimple()
+        {
+            string groupField = "hotel";
+            FieldType customType = new FieldType();
+            customType.Stored = true;
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                Random(),
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+            bool canUseDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool useDv = canUseDV && Random().nextBoolean();
+
+            // 0
+            Document doc = new Document();
+            AddField(doc, groupField, "a", useDv);
+            AddField(doc, "airport", "ams", useDv);
+            AddField(doc, "duration", "5", useDv);
+            w.AddDocument(doc);
+
+            // 1
+            doc = new Document();
+            AddField(doc, groupField, "a", useDv);
+            AddField(doc, "airport", "dus", useDv);
+            AddField(doc, "duration", "10", useDv);
+            w.AddDocument(doc);
+
+            // 2
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            AddField(doc, "airport", "ams", useDv);
+            AddField(doc, "duration", "10", useDv);
+            w.AddDocument(doc);
+            w.Commit(); // To ensure a second segment
+
+            // 3
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            AddField(doc, "airport", "ams", useDv);
+            AddField(doc, "duration", "5", useDv);
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            AddField(doc, "airport", "ams", useDv);
+            AddField(doc, "duration", "5", useDv);
+            w.AddDocument(doc);
+
+            IndexSearcher indexSearcher = NewSearcher(w.Reader);
+
+            List<TermGroupFacetCollector.FacetEntry> entries = null;
+            AbstractGroupFacetCollector groupedAirportFacetCollector = null;
+            TermGroupFacetCollector.GroupedFacetResult airportResult = null;
+
+            foreach (int limit in new int[] { 2, 10, 100, int.MaxValue
+    })
+            {
+                // any of these limits is plenty for the data we have
+
+                groupedAirportFacetCollector = CreateRandomCollector
+                  (useDv ? "hotel_dv" : "hotel",
+                   useDv ? "airport_dv" : "airport", null, false);
+                indexSearcher.Search(new MatchAllDocsQuery(), groupedAirportFacetCollector);
+                int maxOffset = 5;
+                airportResult = groupedAirportFacetCollector.MergeSegmentResults
+                    (int.MaxValue == limit ? limit : maxOffset + limit, 0, false);
+
+
+                assertEquals(3, airportResult.TotalCount);
+                assertEquals(0, airportResult.TotalMissingCount);
+
+                entries = airportResult.GetFacetEntries(maxOffset, limit);
+                assertEquals(0, entries.size());
+
+                entries = airportResult.GetFacetEntries(0, limit);
+                assertEquals(2, entries.size());
+                assertEquals("ams", entries[0].Value.Utf8ToString());
+                assertEquals(2, entries[0].Count);
+                assertEquals("dus", entries[1].Value.Utf8ToString());
+                assertEquals(1, entries[1].Count);
+
+                entries = airportResult.GetFacetEntries(1, limit);
+                assertEquals(1, entries.size());
+                assertEquals("dus", entries[0].Value.Utf8ToString());
+                assertEquals(1, entries[0].Count);
+            }
+
+            AbstractGroupFacetCollector groupedDurationFacetCollector = CreateRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "duration_dv" : "duration", null, false);
+            indexSearcher.Search(new MatchAllDocsQuery(), groupedDurationFacetCollector);
+            TermGroupFacetCollector.GroupedFacetResult durationResult = groupedDurationFacetCollector.MergeSegmentResults(10, 0, false);
+            assertEquals(4, durationResult.TotalCount);
+            assertEquals(0, durationResult.TotalMissingCount);
+
+            entries = durationResult.GetFacetEntries(0, 10);
+            assertEquals(2, entries.size());
+            assertEquals("10", entries[0].Value.Utf8ToString());
+            assertEquals(2, entries[0].Count);
+            assertEquals("5", entries[1].Value.Utf8ToString());
+            assertEquals(2, entries[1].Count);
+
+            // 5
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            // missing airport
+            if (useDv)
+            {
+                AddField(doc, "airport", "", useDv);
+            }
+            AddField(doc, "duration", "5", useDv);
+            w.AddDocument(doc);
+
+            // 6
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            AddField(doc, "airport", "bru", useDv);
+            AddField(doc, "duration", "10", useDv);
+            w.AddDocument(doc);
+
+            // 7
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            AddField(doc, "airport", "bru", useDv);
+            AddField(doc, "duration", "15", useDv);
+            w.AddDocument(doc);
+
+            // 8
+            doc = new Document();
+            AddField(doc, groupField, "a", useDv);
+            AddField(doc, "airport", "bru", useDv);
+            AddField(doc, "duration", "10", useDv);
+            w.AddDocument(doc);
+
+            indexSearcher.IndexReader.Dispose();
+            indexSearcher = NewSearcher(w.Reader);
+            groupedAirportFacetCollector = CreateRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "airport_dv" : "airport", null, !useDv);
+            indexSearcher.Search(new MatchAllDocsQuery(), groupedAirportFacetCollector);
+            airportResult = groupedAirportFacetCollector.MergeSegmentResults(3, 0, true);
+            entries = airportResult.GetFacetEntries(1, 2);
+            assertEquals(2, entries.size());
+            if (useDv)
+            {
+                assertEquals(6, airportResult.TotalCount);
+                assertEquals(0, airportResult.TotalMissingCount);
+                assertEquals("bru", entries[0].Value.Utf8ToString());
+                assertEquals(2, entries[0].Count);
+                assertEquals("", entries[1].Value.Utf8ToString());
+                assertEquals(1, entries[1].Count);
+            }
+            else
+            {
+                assertEquals(5, airportResult.TotalCount);
+                assertEquals(1, airportResult.TotalMissingCount);
+                assertEquals("bru", entries[0].Value.Utf8ToString());
+                assertEquals(2, entries[0].Count);
+                assertEquals("dus", entries[1].Value.Utf8ToString());
+                assertEquals(1, entries[1].Count);
+            }
+
+            groupedDurationFacetCollector = CreateRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "duration_dv" : "duration", null, false);
+            indexSearcher.Search(new MatchAllDocsQuery(), groupedDurationFacetCollector);
+            durationResult = groupedDurationFacetCollector.MergeSegmentResults(10, 2, true);
+            assertEquals(5, durationResult.TotalCount);
+            assertEquals(0, durationResult.TotalMissingCount);
+
+            entries = durationResult.GetFacetEntries(1, 1);
+            assertEquals(1, entries.size());
+            assertEquals("5", entries[0].Value.Utf8ToString());
+            assertEquals(2, entries[0].Count);
+
+            // 9
+            doc = new Document();
+            AddField(doc, groupField, "c", useDv);
+            AddField(doc, "airport", "bru", useDv);
+            AddField(doc, "duration", "15", useDv);
+            w.AddDocument(doc);
+
+            // 10
+            doc = new Document();
+            AddField(doc, groupField, "c", useDv);
+            AddField(doc, "airport", "dus", useDv);
+            AddField(doc, "duration", "10", useDv);
+            w.AddDocument(doc);
+
+            indexSearcher.IndexReader.Dispose();
+            indexSearcher = NewSearcher(w.Reader);
+            groupedAirportFacetCollector = CreateRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "airport_dv" : "airport", null, false);
+            indexSearcher.Search(new MatchAllDocsQuery(), groupedAirportFacetCollector);
+            airportResult = groupedAirportFacetCollector.MergeSegmentResults(10, 0, false);
+            entries = airportResult.GetFacetEntries(0, 10);
+            if (useDv)
+            {
+                assertEquals(8, airportResult.TotalCount);
+                assertEquals(0, airportResult.TotalMissingCount);
+                assertEquals(4, entries.size());
+                assertEquals("", entries[0].Value.Utf8ToString());
+                assertEquals(1, entries[0].Count);
+                assertEquals("ams", entries[1].Value.Utf8ToString());
+                assertEquals(2, entries[1].Count);
+                assertEquals("bru", entries[2].Value.Utf8ToString());
+                assertEquals(3, entries[2].Count);
+                assertEquals("dus", entries[3].Value.Utf8ToString());
+                assertEquals(2, entries[3].Count);
+            }
+            else
+            {
+                assertEquals(7, airportResult.TotalCount);
+                assertEquals(1, airportResult.TotalMissingCount);
+                assertEquals(3, entries.size());
+                assertEquals("ams", entries[0].Value.Utf8ToString());
+                assertEquals(2, entries[0].Count);
+                assertEquals("bru", entries[1].Value.Utf8ToString());
+                assertEquals(3, entries[1].Count);
+                assertEquals("dus", entries[2].Value.Utf8ToString());
+                assertEquals(2, entries[2].Count);
+            }
+
+            groupedDurationFacetCollector = CreateRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "duration_dv" : "duration", "1", false);
+            indexSearcher.Search(new MatchAllDocsQuery(), groupedDurationFacetCollector);
+            durationResult = groupedDurationFacetCollector.MergeSegmentResults(10, 0, true);
+            assertEquals(5, durationResult.TotalCount);
+            assertEquals(0, durationResult.TotalMissingCount);
+
+            entries = durationResult.GetFacetEntries(0, 10);
+            assertEquals(2, entries.size());
+            assertEquals("10", entries[0].Value.Utf8ToString());
+            assertEquals(3, entries[0].Count);
+            assertEquals("15", entries[1].Value.Utf8ToString());
+            assertEquals(2, entries[1].Count);
+
+            w.Dispose();
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public void TestMVGroupedFacetingWithDeletes()
+        {
+            string groupField = "hotel";
+            FieldType customType = new FieldType();
+            customType.Stored = (true);
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                Random(),
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(Random())).SetMergePolicy(NoMergePolicy.COMPOUND_FILES));
+            bool useDv = false;
+
+            // Cannot assert this since we use NoMergePolicy:
+            w.DoRandomForceMergeAssert = (false);
+
+            // 0
+            Document doc = new Document();
+            doc.Add(new StringField("x", "x", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 1
+            doc = new Document();
+            AddField(doc, groupField, "a", useDv);
+            doc.Add(new StringField("airport", "ams", Field.Store.NO));
+            w.AddDocument(doc);
+
+            w.Commit();
+            w.DeleteDocuments(new TermQuery(new Term("airport", "ams")));
+
+            // 2
+            doc = new Document();
+            AddField(doc, groupField, "a", useDv);
+            doc.Add(new StringField("airport", "ams", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 3
+            doc = new Document();
+            AddField(doc, groupField, "a", useDv);
+            doc.Add(new StringField("airport", "dus", Field.Store.NO));
+
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            doc.Add(new StringField("airport", "ams", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 5
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            doc.Add(new StringField("airport", "ams", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 6
+            doc = new Document();
+            AddField(doc, groupField, "b", useDv);
+            doc.Add(new StringField("airport", "ams", Field.Store.NO));
+            w.AddDocument(doc);
+            w.Commit();
+
+            // 7
+            doc = new Document();
+            doc.Add(new StringField("x", "x", Field.Store.NO));
+            w.AddDocument(doc);
+            w.Commit();
+
+            w.Dispose();
+            IndexSearcher indexSearcher = NewSearcher(DirectoryReader.Open(dir));
+            AbstractGroupFacetCollector groupedAirportFacetCollector = CreateRandomCollector(groupField, "airport", null, true);
+            indexSearcher.Search(new MatchAllDocsQuery(), groupedAirportFacetCollector);
+            TermGroupFacetCollector.GroupedFacetResult airportResult = groupedAirportFacetCollector.MergeSegmentResults(10, 0, false);
+            assertEquals(3, airportResult.TotalCount);
+            assertEquals(1, airportResult.TotalMissingCount);
+
+            List<TermGroupFacetCollector.FacetEntry> entries = airportResult.GetFacetEntries(0, 10);
+            assertEquals(2, entries.size());
+            assertEquals("ams", entries[0].Value.Utf8ToString());
+            assertEquals(2, entries[0].Count);
+            assertEquals("dus", entries[1].Value.Utf8ToString());
+            assertEquals(1, entries[1].Count);
+
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        private void AddField(Document doc, string field, string value, bool canUseIDV)
+        {
+            doc.Add(new StringField(field, value, Field.Store.NO));
+            if (canUseIDV)
+            {
+                doc.Add(new SortedDocValuesField(field + "_dv", new BytesRef(value)));
+            }
+        }
+
+        [Test]
+        public void TestRandom()
+        {
+            Random random = Random();
+            int numberOfRuns = TestUtil.NextInt(random, 3, 6);
+            for (int indexIter = 0; indexIter < numberOfRuns; indexIter++)
+            {
+                bool multipleFacetsPerDocument = random.nextBoolean();
+                IndexContext context = CreateIndexContext(multipleFacetsPerDocument);
+                IndexSearcher searcher = NewSearcher(context.indexReader);
+
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: searcher=" + searcher);
+                }
+
+                for (int searchIter = 0; searchIter < 100; searchIter++)
+                {
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("TEST: searchIter=" + searchIter);
+                    }
+                    bool useDv = !multipleFacetsPerDocument && context.useDV && random.nextBoolean();
+                    string searchTerm = context.contentStrings[random.nextInt(context.contentStrings.Length)];
+                    int limit = random.nextInt(context.facetValues.size());
+                    int offset = random.nextInt(context.facetValues.size() - limit);
+                    int size = offset + limit;
+                    int minCount = random.nextBoolean() ? 0 : random.nextInt(1 + context.facetWithMostGroups / 10);
+                    bool orderByCount = random.nextBoolean();
+                    string randomStr = GetFromSet(context.facetValues, random.nextInt(context.facetValues.size()));
+                    string facetPrefix;
+                    if (randomStr == null)
+                    {
+                        facetPrefix = null;
+                    }
+                    else
+                    {
+                        int codePointLen = randomStr.CodePointCount(0, randomStr.Length);
+                        int randomLen = random.nextInt(codePointLen);
+                        if (codePointLen == randomLen - 1)
+                        {
+                            facetPrefix = null;
+                        }
+                        else
+                        {
+                            int end = randomStr.OffsetByCodePoints(0, randomLen);
+                            facetPrefix = random.nextBoolean() ? null : randomStr.Substring(end);
+                        }
+                    }
+
+                    GroupedFacetResult expectedFacetResult = CreateExpectedFacetResult(searchTerm, context, offset, limit, minCount, orderByCount, facetPrefix);
+                    AbstractGroupFacetCollector groupFacetCollector = CreateRandomCollector(useDv ? "group_dv" : "group", useDv ? "facet_dv" : "facet", facetPrefix, multipleFacetsPerDocument);
+                    searcher.Search(new TermQuery(new Term("content", searchTerm)), groupFacetCollector);
+                    TermGroupFacetCollector.GroupedFacetResult actualFacetResult = groupFacetCollector.MergeSegmentResults(size, minCount, orderByCount);
+
+                    List<TermGroupFacetCollector.FacetEntry> expectedFacetEntries = expectedFacetResult.getFacetEntries();
+                    List<TermGroupFacetCollector.FacetEntry> actualFacetEntries = actualFacetResult.GetFacetEntries(offset, limit);
+
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("Use DV: " + useDv);
+                        Console.WriteLine("Collector: " + groupFacetCollector.GetType().Name);
+                        Console.WriteLine("Num group: " + context.numGroups);
+                        Console.WriteLine("Num doc: " + context.numDocs);
+                        Console.WriteLine("Index iter: " + indexIter);
+                        Console.WriteLine("multipleFacetsPerDocument: " + multipleFacetsPerDocument);
+                        Console.WriteLine("Search iter: " + searchIter);
+
+                        Console.WriteLine("Search term: " + searchTerm);
+                        Console.WriteLine("Min count: " + minCount);
+                        Console.WriteLine("Facet offset: " + offset);
+                        Console.WriteLine("Facet limit: " + limit);
+                        Console.WriteLine("Facet prefix: " + facetPrefix);
+                        Console.WriteLine("Order by count: " + orderByCount);
+
+                        Console.WriteLine("\n=== Expected: \n");
+                        Console.WriteLine("Total count " + expectedFacetResult.getTotalCount());
+                        Console.WriteLine("Total missing count " + expectedFacetResult.getTotalMissingCount());
+                        int counter = 0;
+                        foreach (TermGroupFacetCollector.FacetEntry expectedFacetEntry in expectedFacetEntries)
+                        {
+                            Console.WriteLine(
+                                string.Format(CultureInfo.InvariantCulture,
+                                    "{0}. Expected facet value {1} with count {2}",
+                                    counter++, expectedFacetEntry.Value.Utf8ToString(), expectedFacetEntry.Count
+                                )
+                            );
+                        }
+
+                        Console.WriteLine("\n=== Actual: \n");
+                        Console.WriteLine("Total count " + actualFacetResult.TotalCount);
+                        Console.WriteLine("Total missing count " + actualFacetResult.TotalMissingCount);
+                        counter = 0;
+                        foreach (TermGroupFacetCollector.FacetEntry actualFacetEntry in actualFacetEntries)
+                        {
+                            Console.WriteLine(
+                                string.Format(CultureInfo.InvariantCulture,
+                                    "{0}. Actual facet value {1} with count {2}",
+                                    counter++, actualFacetEntry.Value.Utf8ToString(), actualFacetEntry.Count
+                                )
+                            );
+                        }
+                        Console.WriteLine("\n===================================================================================");
+                    }
+
+                    assertEquals(expectedFacetResult.getTotalCount(), actualFacetResult.TotalCount);
+                    assertEquals(expectedFacetResult.getTotalMissingCount(), actualFacetResult.TotalMissingCount);
+                    assertEquals(expectedFacetEntries.size(), actualFacetEntries.size());
+                    for (int i = 0; i < expectedFacetEntries.size(); i++)
+                    {
+                        TermGroupFacetCollector.FacetEntry expectedFacetEntry = expectedFacetEntries[i];
+                        TermGroupFacetCollector.FacetEntry actualFacetEntry = actualFacetEntries[i];
+                        assertEquals("i=" + i + ": " + expectedFacetEntry.Value.Utf8ToString() + " != " + actualFacetEntry.Value.Utf8ToString(), expectedFacetEntry.Value, actualFacetEntry.Value);
+                        assertEquals("i=" + i + ": " + expectedFacetEntry.Count + " != " + actualFacetEntry.Count, expectedFacetEntry.Count, actualFacetEntry.Count);
+                    }
+                }
+
+                context.indexReader.Dispose();
+                context.dir.Dispose();
+            }
+        }
+
+        internal class ComparerAnonymousHelper1 : IComparer<string>
+        {
+            public int Compare(string a, string b)
+            {
+                if (a == b)
+                {
+                    return 0;
+                }
+                else if (a == null)
+                {
+                    return -1;
+                }
+                else if (b == null)
+                {
+                    return 1;
+                }
+                else
+                {
+                    return a.CompareToOrdinal(b);
+                }
+            }
+        }
+
+        private IndexContext CreateIndexContext(bool multipleFacetValuesPerDocument)
+        {
+            Random random = Random();
+            int numDocs = TestUtil.NextInt(random, 138, 1145) * RANDOM_MULTIPLIER;
+            int numGroups = TestUtil.NextInt(random, 1, numDocs / 4);
+            int numFacets = TestUtil.NextInt(random, 1, numDocs / 6);
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: numDocs=" + numDocs + " numGroups=" + numGroups);
+            }
+
+            List<string> groups = new List<string>();
+            for (int i = 0; i < numGroups; i++)
+            {
+                groups.Add(GenerateRandomNonEmptyString());
+            }
+            List<string> facetValues = new List<string>();
+            for (int i = 0; i < numFacets; i++)
+            {
+                facetValues.Add(GenerateRandomNonEmptyString());
+            }
+            string[] contentBrs = new string[TestUtil.NextInt(random, 2, 20)];
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: create fake content");
+            }
+            for (int contentIDX = 0; contentIDX < contentBrs.Length; contentIDX++)
+            {
+                contentBrs[contentIDX] = GenerateRandomNonEmptyString();
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  content=" + contentBrs[contentIDX]);
+                }
+            }
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter writer = new RandomIndexWriter(
+                random,
+                dir,
+                NewIndexWriterConfig(
+                    TEST_VERSION_CURRENT,
+                    new MockAnalyzer(random)
+                )
+            );
+            bool canUseDV = !"Lucene3x".equals(writer.w.Config.Codec.Name);
+            bool useDv = canUseDV && !multipleFacetValuesPerDocument && random.nextBoolean();
+
+            Document doc = new Document();
+            Document docNoGroup = new Document();
+            Document docNoFacet = new Document();
+            Document docNoGroupNoFacet = new Document();
+            Field group = NewStringField("group", "", Field.Store.NO);
+            Field groupDc = new SortedDocValuesField("group_dv", new BytesRef());
+            if (useDv)
+            {
+                doc.Add(groupDc);
+                docNoFacet.Add(groupDc);
+            }
+            doc.Add(group);
+            docNoFacet.Add(group);
+            Field[] facetFields;
+            if (useDv)
+            {
+                Debug.Assert(!multipleFacetValuesPerDocument);
+                facetFields = new Field[2];
+                facetFields[0] = NewStringField("facet", "", Field.Store.NO);
+                doc.Add(facetFields[0]);
+                docNoGroup.Add(facetFields[0]);
+                facetFields[1] = new SortedDocValuesField("facet_dv", new BytesRef());
+                doc.Add(facetFields[1]);
+                docNoGroup.Add(facetFields[1]);
+            }
+            else
+            {
+                facetFields = multipleFacetValuesPerDocument ? new Field[2 + random.nextInt(6)] : new Field[1];
+                for (int i = 0; i < facetFields.Length; i++)
+                {
+                    facetFields[i] = NewStringField("facet", "", Field.Store.NO);
+                    doc.Add(facetFields[i]);
+                    docNoGroup.Add(facetFields[i]);
+                }
+            }
+            Field content = NewStringField("content", "", Field.Store.NO);
+            doc.Add(content);
+            docNoGroup.Add(content);
+            docNoFacet.Add(content);
+            docNoGroupNoFacet.Add(content);
+
+            ISet<string> uniqueFacetValues = new SortedSet<string>(new ComparerAnonymousHelper1());
+            //    ISet<string> uniqueFacetValues = new SortedSet<string>(new Comparator<String>() {
+
+            //      @Override
+            //      public int compare(String a, String b)
+            //{
+            //    if (a == b)
+            //    {
+            //        return 0;
+            //    }
+            //    else if (a == null)
+            //    {
+            //        return -1;
+            //    }
+            //    else if (b == null)
+            //    {
+            //        return 1;
+            //    }
+            //    else
+            //    {
+            //        return a.compareTo(b);
+            //    }
+            //}
+
+            //    });
+            // LUCENENET NOTE: Need HashMap here because of null keys
+            IDictionary<string, HashMap<string, ISet<string>>> searchTermToFacetToGroups = new Dictionary<string, HashMap<string, ISet<string>>>();
+            int facetWithMostGroups = 0;
+            for (int i = 0; i < numDocs; i++)
+            {
+                string groupValue;
+                if (random.nextInt(24) == 17)
+                {
+                    // So we test the "doc doesn't have the group'd
+                    // field" case:
+                    if (useDv)
+                    {
+                        groupValue = "";
+                    }
+                    else
+                    {
+                        groupValue = null;
+                    }
+                }
+                else
+                {
+                    groupValue = groups[random.nextInt(groups.size())];
+                }
+
+                string contentStr = contentBrs[random.nextInt(contentBrs.Length)];
+                if (!searchTermToFacetToGroups.ContainsKey(contentStr))
+                {
+                    searchTermToFacetToGroups[contentStr] = new HashMap<string, ISet<string>>();
+                }
+                IDictionary<string, ISet<string>> facetToGroups = searchTermToFacetToGroups[contentStr];
+
+                List<string> facetVals = new List<string>();
+                if (useDv || random.nextInt(24) != 18)
+                {
+                    if (useDv)
+                    {
+                        String facetValue = facetValues[random.nextInt(facetValues.size())];
+                        uniqueFacetValues.add(facetValue);
+                        if (!facetToGroups.ContainsKey(facetValue))
+                        {
+                            facetToGroups[facetValue] = new HashSet<string>();
+                        }
+                        ISet<string> groupsInFacet = facetToGroups[facetValue];
+                        groupsInFacet.add(groupValue);
+                        if (groupsInFacet.size() > facetWithMostGroups)
+                        {
+                            facetWithMostGroups = groupsInFacet.size();
+                        }
+                        facetFields[0].StringValue = (facetValue);
+                        facetFields[1].BytesValue = (new BytesRef(facetValue));
+                        facetVals.Add(facetValue);
+                    }
+                    else
+                    {
+                        foreach (Field facetField in facetFields)
+                        {
+                            string facetValue = facetValues[random.nextInt(facetValues.size())];
+                            uniqueFacetValues.add(facetValue);
+                            if (!facetToGroups.ContainsKey(facetValue))
+                            {
+                                facetToGroups[facetValue] = new HashSet<string>();
+                            }
+                            ISet<string> groupsInFacet = facetToGroups[facetValue];
+                            groupsInFacet.add(groupValue);
+                            if (groupsInFacet.size() > facetWithMostGroups)
+                            {
+                                facetWithMostGroups = groupsInFacet.size();
+                            }
+                            facetField.StringValue = (facetValue);
+                            facetVals.Add(facetValue);
+                        }
+                    }
+                }
+                else
+                {
+                    uniqueFacetValues.add(null);
+                    if (!facetToGroups.ContainsKey(null))
+                    {
+                        facetToGroups.Put(null, new HashSet<string>());
+                    }
+                    ISet<string> groupsInFacet = facetToGroups[null];
+                    groupsInFacet.add(groupValue);
+                    if (groupsInFacet.size() > facetWithMostGroups)
+                    {
+                        facetWithMostGroups = groupsInFacet.size();
+                    }
+                }
+
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  doc content=" + contentStr + " group=" + (groupValue == null ? "null" : groupValue) + " facetVals=" + facetVals);
+                }
+
+                if (groupValue != null)
+                {
+                    if (useDv)
+                    {
+                        groupDc.BytesValue = (new BytesRef(groupValue));
+                    }
+                    group.StringValue = (groupValue);
+                }
+                else if (useDv)
+                {
+                    // DV cannot have missing values:
+                    groupDc.BytesValue = (new BytesRef());
+                }
+                content.StringValue = (contentStr);
+                if (groupValue == null && !facetVals.Any())
+                {
+                    writer.AddDocument(docNoGroupNoFacet);
+                }
+                else if (!facetVals.Any())
+                {
+                    writer.AddDocument(docNoFacet);
+                }
+                else if (groupValue == null)
+                {
+                    writer.AddDocument(docNoGroup);
+                }
+                else
+                {
+                    writer.AddDocument(doc);
+                }
+            }
+
+            DirectoryReader reader = writer.Reader;
+            writer.Dispose();
+
+            return new IndexContext(searchTermToFacetToGroups, reader, numDocs, dir, facetWithMostGroups, numGroups, contentBrs, uniqueFacetValues, useDv);
+        }
+
+        internal class ComparerAnonymousHelper2 : IComparer<TermGroupFacetCollector.FacetEntry>
+        {
+            private readonly bool orderByCount;
+
+            public ComparerAnonymousHelper2(bool orderByCount)
+            {
+                this.orderByCount = orderByCount;
+            }
+
+            public int Compare(AbstractGroupFacetCollector.FacetEntry a, AbstractGroupFacetCollector.FacetEntry b)
+            {
+                if (orderByCount)
+                {
+                    int cmp = b.Count - a.Count;
+                    if (cmp != 0)
+                    {
+                        return cmp;
+                    }
+                }
+                return a.Value.CompareTo(b.Value);
+            }
+        }
+
+        private GroupedFacetResult CreateExpectedFacetResult(string searchTerm, IndexContext context, int offset, int limit, int minCount, bool orderByCount, string facetPrefix)
+        {
+            //IDictionary<string, ISet<string>> facetGroups = context.searchTermToFacetGroups.get(searchTerm);
+            //if (facetGroups == null)
+            HashMap<string, ISet<string>> facetGroups;
+            if (!context.searchTermToFacetGroups.TryGetValue(searchTerm, out facetGroups))
+            {
+                facetGroups = new HashMap<string, ISet<string>>();
+            }
+
+            int totalCount = 0;
+            int totalMissCount = 0;
+            ISet<string> facetValues;
+            if (facetPrefix != null)
+            {
+                facetValues = new HashSet<string>();
+                foreach (string facetValue in context.facetValues)
+                {
+                    if (facetValue != null && facetValue.StartsWith(facetPrefix))
+                    {
+                        facetValues.add(facetValue);
+                    }
+                }
+            }
+            else
+            {
+                facetValues = context.facetValues;
+            }
+
+            List<TermGroupFacetCollector.FacetEntry> entries = new List<TermGroupFacetCollector.FacetEntry>(facetGroups.size());
+            // also includes facets with count 0
+            foreach (string facetValue in facetValues)
+            {
+                if (facetValue == null)
+                {
+                    continue;
+                }
+
+                ISet<string> groups = facetGroups.ContainsKey(facetValue) ? facetGroups[facetValue] : null;
+                int count = groups != null ? groups.size() : 0;
+                if (count >= minCount)
+                {
+                    entries.Add(new TermGroupFacetCollector.FacetEntry(new BytesRef(facetValue), count));
+                }
+                totalCount += count;
+            }
+
+            // Only include null count when no facet prefix is specified
+            if (facetPrefix == null)
+            {
+                ISet<string> groups = facetGroups[null];
+                if (groups != null)
+                {
+                    totalMissCount = groups.size();
+                }
+            }
+
+            entries.Sort(new ComparerAnonymousHelper2(orderByCount));
+
+            //    Collections.sort(entries, new Comparator<TermGroupFacetCollector.FacetEntry>() {
+
+            //      @Override
+            //      public int compare(TermGroupFacetCollector.FacetEntry a, TermGroupFacetCollector.FacetEntry b)
+            //{
+            //    if (orderByCount)
+            //    {
+            //        int cmp = b.getCount() - a.getCount();
+            //        if (cmp != 0)
+            //        {
+            //            return cmp;
+            //        }
+            //    }
+            //    return a.getValue().compareTo(b.getValue());
+            //}
+
+            //    });
+
+            int endOffset = offset + limit;
+            List<TermGroupFacetCollector.FacetEntry> entriesResult;
+            if (offset >= entries.size())
+            {
+                entriesResult = new List<TermGroupFacetCollector.FacetEntry>();
+            }
+            else if (endOffset >= entries.size())
+            {
+                //entriesResult = (List<TermGroupFacetCollector.FacetEntry>)entries.SubList(offset, entries.size());
+                entriesResult = entries.GetRange(offset, entries.size() - offset);
+            }
+            else
+            {
+                //entriesResult = (List<TermGroupFacetCollector.FacetEntry>)entries.SubList(offset, endOffset);
+                entriesResult = entries.GetRange(offset, endOffset - offset);
+            }
+            return new GroupedFacetResult(totalCount, totalMissCount, entriesResult);
+        }
+
+        private AbstractGroupFacetCollector CreateRandomCollector(string groupField, string facetField, string facetPrefix, bool multipleFacetsPerDocument)
+        {
+            BytesRef facetPrefixBR = facetPrefix == null ? null : new BytesRef(facetPrefix);
+            // DocValues cannot be multi-valued:
+            Debug.Assert(!multipleFacetsPerDocument || !groupField.EndsWith("_dv"));
+            return TermGroupFacetCollector.CreateTermGroupFacetCollector(groupField, facetField, multipleFacetsPerDocument, facetPrefixBR, Random().nextInt(1024));
+        }
+
+        private string GetFromSet(ISet<string> set, int index)
+        {
+            int currentIndex = 0;
+            foreach (string bytesRef in set)
+            {
+                if (currentIndex++ == index)
+                {
+                    return bytesRef;
+                }
+            }
+
+            return null;
+        }
+
+        internal class IndexContext
+        {
+            internal readonly int numDocs;
+            internal readonly DirectoryReader indexReader;
+            internal readonly IDictionary<string, HashMap<string, ISet<string>>> searchTermToFacetGroups;
+            internal readonly ISet<string> facetValues;
+            internal readonly Directory dir;
+            internal readonly int facetWithMostGroups;
+            internal readonly int numGroups;
+            internal readonly string[] contentStrings;
+            internal readonly bool useDV;
+
+            public IndexContext(IDictionary<string, HashMap<string, ISet<string>>> searchTermToFacetGroups, DirectoryReader r,
+                                int numDocs, Directory dir, int facetWithMostGroups, int numGroups, string[] contentStrings, ISet<string> facetValues, bool useDV)
+            {
+                this.searchTermToFacetGroups = searchTermToFacetGroups;
+                this.indexReader = r;
+                this.numDocs = numDocs;
+                this.dir = dir;
+                this.facetWithMostGroups = facetWithMostGroups;
+                this.numGroups = numGroups;
+                this.contentStrings = contentStrings;
+                this.facetValues = facetValues;
+                this.useDV = useDV;
+            }
+        }
+
+        internal class GroupedFacetResult
+        {
+
+            internal readonly int totalCount;
+            internal readonly int totalMissingCount;
+            internal readonly List<TermGroupFacetCollector.FacetEntry> facetEntries;
+
+            internal GroupedFacetResult(int totalCount, int totalMissingCount, List<TermGroupFacetCollector.FacetEntry> facetEntries)
+            {
+                this.totalCount = totalCount;
+                this.totalMissingCount = totalMissingCount;
+                this.facetEntries = facetEntries;
+            }
+
+            public int getTotalCount()
+            {
+                return totalCount;
+            }
+
+            public int getTotalMissingCount()
+            {
+                return totalMissingCount;
+            }
+
+            public List<TermGroupFacetCollector.FacetEntry> getFacetEntries()
+            {
+                return facetEntries;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
new file mode 100644
index 0000000..8f49614
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
@@ -0,0 +1,245 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Queries.Function.ValueSources;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using Lucene.Net.Util.Mutable;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    public class GroupingSearchTest : LuceneTestCase
+    {
+        // Tests some very basic usages...
+        [Test]
+        public void testBasic()
+        {
+
+            string groupField = "author";
+
+            FieldType customType = new FieldType();
+            customType.Stored = (true);
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                Random(),
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            List<Document> documents = new List<Document>();
+            // 0
+            Document doc = new Document();
+            addGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "random text", Field.Store.YES));
+            doc.Add(new Field("id", "1", customType));
+            documents.Add(doc);
+
+            // 1
+            doc = new Document();
+            addGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "some more random text", Field.Store.YES));
+            doc.Add(new Field("id", "2", customType));
+            documents.Add(doc);
+
+            // 2
+            doc = new Document();
+            addGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "some more random textual data", Field.Store.YES));
+            doc.Add(new Field("id", "3", customType));
+            doc.Add(new StringField("groupend", "x", Field.Store.NO));
+            documents.Add(doc);
+            w.AddDocuments(documents);
+            documents.Clear();
+
+            // 3
+            doc = new Document();
+            addGroupField(doc, groupField, "author2", canUseIDV);
+            doc.Add(new TextField("content", "some random text", Field.Store.YES));
+            doc.Add(new Field("id", "4", customType));
+            doc.Add(new StringField("groupend", "x", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            addGroupField(doc, groupField, "author3", canUseIDV);
+            doc.Add(new TextField("content", "some more random text", Field.Store.YES));
+            doc.Add(new Field("id", "5", customType));
+            documents.Add(doc);
+
+            // 5
+            doc = new Document();
+            addGroupField(doc, groupField, "author3", canUseIDV);
+            doc.Add(new TextField("content", "random", Field.Store.YES));
+            doc.Add(new Field("id", "6", customType));
+            doc.Add(new StringField("groupend", "x", Field.Store.NO));
+            documents.Add(doc);
+            w.AddDocuments(documents);
+            documents.Clear();
+
+            // 6 -- no author field
+            doc = new Document();
+            doc.Add(new TextField("content", "random word stuck in alot of other text", Field.Store.YES));
+            doc.Add(new Field("id", "6", customType));
+            doc.Add(new StringField("groupend", "x", Field.Store.NO));
+
+            w.AddDocument(doc);
+
+            IndexSearcher indexSearcher = NewSearcher(w.Reader);
+            w.Dispose();
+
+            Sort groupSort = Sort.RELEVANCE;
+            GroupingSearch groupingSearch = createRandomGroupingSearch(groupField, groupSort, 5, canUseIDV);
+
+            var groups = groupingSearch.Search(indexSearcher, (Filter)null, new TermQuery(new Index.Term("content", "random")), 0, 10);
+
+            assertEquals(7, groups.totalHitCount);
+            assertEquals(7, groups.totalGroupedHitCount);
+            assertEquals(4, groups.groups.length);
+
+            // relevance order: 5, 0, 3, 4, 1, 2, 6
+
+            // the later a document is added the higher this docId
+            // value
+            GroupDocs <?> group = groups.groups[0];
+            compareGroupValue("author3", group);
+            assertEquals(2, group.scoreDocs.length);
+            assertEquals(5, group.scoreDocs[0].doc);
+            assertEquals(4, group.scoreDocs[1].doc);
+            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
+
+            group = groups.groups[1];
+            compareGroupValue("author1", group);
+            assertEquals(3, group.scoreDocs.length);
+            assertEquals(0, group.scoreDocs[0].doc);
+            assertEquals(1, group.scoreDocs[1].doc);
+            assertEquals(2, group.scoreDocs[2].doc);
+            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
+            assertTrue(group.scoreDocs[1].score > group.scoreDocs[2].score);
+
+            group = groups.groups[2];
+            compareGroupValue("author2", group);
+            assertEquals(1, group.scoreDocs.length);
+            assertEquals(3, group.scoreDocs[0].doc);
+
+            group = groups.groups[3];
+            compareGroupValue(null, group);
+            assertEquals(1, group.scoreDocs.length);
+            assertEquals(6, group.scoreDocs[0].doc);
+
+            Filter lastDocInBlock = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Index.Term("groupend", "x"))));
+            groupingSearch = new GroupingSearch(lastDocInBlock);
+            groups = groupingSearch.Search(indexSearcher, null, new TermQuery(new Index.Term("content", "random")), 0, 10);
+
+            assertEquals(7, groups.totalHitCount);
+            assertEquals(7, groups.totalGroupedHitCount);
+            assertEquals(4, groups.totalGroupCount.longValue());
+            assertEquals(4, groups.groups.length);
+
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        private void addGroupField(Document doc, string groupField, string value, bool canUseIDV)
+        {
+            doc.Add(new TextField(groupField, value, Field.Store.YES));
+            if (canUseIDV)
+            {
+                doc.Add(new SortedDocValuesField(groupField, new BytesRef(value)));
+            }
+        }
+
+        private void compareGroupValue(string expected, GroupDocs<?> group)
+        {
+            if (expected == null)
+            {
+                if (group.groupValue == null)
+                {
+                    return;
+                }
+                else if (group.groupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
+                {
+                    return;
+                }
+                else if (((BytesRef)group.groupValue).length == 0)
+                {
+                    return;
+                }
+                fail();
+            }
+
+            if (group.groupValue.GetType().IsAssignableFrom(typeof(BytesRef)))
+            {
+                assertEquals(new BytesRef(expected), group.groupValue);
+            }
+            else if (group.groupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
+            {
+                MutableValueStr v = new MutableValueStr();
+                v.value = new BytesRef(expected);
+                assertEquals(v, group.groupValue);
+            }
+            else
+            {
+                fail();
+            }
+        }
+
+        private GroupingSearch createRandomGroupingSearch(String groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
+        {
+            GroupingSearch groupingSearch;
+            if (Random().nextBoolean())
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                groupingSearch = new GroupingSearch(vs, new Dictionary());
+            }
+            else
+            {
+                groupingSearch = new GroupingSearch(groupField);
+            }
+
+            groupingSearch.SetGroupSort(groupSort);
+            groupingSearch.SetGroupDocsLimit(docsInGroup);
+
+            if (Random().nextBoolean())
+            {
+                groupingSearch.SetCachingInMB(4.0, true);
+            }
+
+            return groupingSearch;
+        }
+
+        [Test]
+        public void testSetAllGroups()
+        {
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                Random(),
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+            Document doc = new Document();
+            doc.Add(NewField("group", "foo", StringField.TYPE_NOT_STORED));
+            w.AddDocument(doc);
+
+            IndexSearcher indexSearcher = NewSearcher(w.Reader);
+            w.Dispose();
+
+            GroupingSearch gs = new GroupingSearch("group");
+            gs.SetAllGroups(true);
+            TopGroups <?> groups = gs.Search(indexSearcher, null, new TermQuery(new Index.Term("group", "foo")), 0, 10);
+            assertEquals(1, groups.totalHitCount);
+            //assertEquals(1, groups.totalGroupCount.intValue());
+            assertEquals(1, groups.totalGroupedHitCount);
+            assertEquals(1, gs.GetAllMatchingGroups().size());
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
new file mode 100644
index 0000000..806839d
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
@@ -0,0 +1,85 @@
+\ufeff<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.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>{C2349F0D-FB66-4544-9C33-4D87F73C6004}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Lucene.Net.Tests.Grouping</RootNamespace>
+    <AssemblyName>Lucene.Net.Tests.Grouping</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="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AbstractGroupingTestCase.cs" />
+    <Compile Include="AllGroupHeadsCollectorTest.cs" />
+    <Compile Include="AllGroupsCollectorTest.cs" />
+    <Compile Include="GroupFacetCollectorTest.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </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.Grouping\Lucene.Net.Grouping.csproj">
+      <Project>{02bab603-067d-48b1-aedd-316849652568}</Project>
+      <Name>Lucene.Net.Grouping</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Lucene.Net.Queries\Lucene.Net.Queries.csproj">
+      <Project>{69D7956C-C2CC-4708-B399-A188FEC384C4}</Project>
+      <Name>Lucene.Net.Queries</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Lucene.Net.TestFramework\Lucene.Net.TestFramework.csproj">
+      <Project>{B2C0D749-CE34-4F62-A15E-00CB2FF5DDB3}</Project>
+      <Name>Lucene.Net.TestFramework</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </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/9d72bcb3/src/Lucene.Net.Tests.Grouping/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/Properties/AssemblyInfo.cs b/src/Lucene.Net.Tests.Grouping/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4944609
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+\ufeffusing 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.Grouping")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Lucene.Net.Tests.Grouping")]
+[assembly: AssemblyCopyright("Copyright �  2016")]
+[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("c2349f0d-fb66-4544-9c33-4d87f73c6004")]
+
+// 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")]


[57/58] [abbrv] lucenenet git commit: Lucene.Net.Grouping: Fixed test failures due to sorting using the wrong algorithm. TimSort doesn't call the IComparer.Compare() method unless the values differ. If it is called when they are the same, the TestGrou

Posted by ni...@apache.org.
Lucene.Net.Grouping: Fixed test failures due to sorting using the wrong algorithm. TimSort doesn't call the IComparer<T>.Compare() method unless the values differ. If it is called when they are the same, the TestGrouping.TestRandom() and AllGroupHeadsCollectorTest.TestRandom() tests fail. Added TODO about differences in sorting APIs.


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

Branch: refs/heads/grouping
Commit: 049718c6cdd9f2170ba4c3227882bf88c03980e1
Parents: a0a61e2
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Mon Nov 7 18:18:05 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:34 2016 +0700

----------------------------------------------------------------------
 .../AllGroupHeadsCollectorTest.cs               | 10 ++++++++-
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs   | 22 ++++++++++++++++++--
 2 files changed, 29 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/049718c6/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index 8d6ca76..38c1721 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -500,7 +500,15 @@ namespace Lucene.Net.Search.Grouping
             foreach (BytesRef groupValue in groupHeads.Keys)
             {
                 List<GroupDoc> docs = groupHeads[groupValue];
-                docs.Sort(GetComparator(docSort, sortByScoreOnly, fieldIdToDocID));
+                // LUCENENET TODO: The original API Collections.Sort does not currently exist.
+                // This call ultimately results in calling TimSort, which is why this line was replaced
+                // with CollectionUtil.TimSort(IList<T>, IComparer<T>).
+                //
+                // NOTE: List.Sort(comparer) won't work in this case because it calls the comparer when the
+                // values are the same, which results in this test failing. TimSort only calls the comparer
+                // when the values differ.
+                //Collections.Sort(docs, GetComparator(docSort, sortByScoreOnly, fieldIdToDocID));
+                CollectionUtil.TimSort(docs, GetComparator(docSort, sortByScoreOnly, fieldIdToDocID));
                 allGroupHeads[i++] = docs[0].id;
             }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/049718c6/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index 1ce5f0e..9d81af9 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -531,7 +531,16 @@ namespace Lucene.Net.Search.Grouping
 
             IComparer<GroupDoc> groupSortComp = GetComparator(groupSort);
 
-            Array.Sort(groupDocs, groupSortComp);
+            // LUCENENET TODO: The original Java API Arrays.Sort does not currently exist.
+            // This call ultimately results in calling TimSort, which is why this line was replaced
+            // with ArrayUtil.TimSort(T[], IComparer<T>).
+            //
+            // NOTE: Array.Sort(comparer) won't work in this case because it calls the comparer when the
+            // values are the same, which results in this test failing. TimSort only calls the comparer
+            // when the values differ.
+            //Arrays.Sort(groupDocs, groupSortComp);
+            ArrayUtil.TimSort(groupDocs, groupSortComp);
+            
             HashMap<BytesRef, List<GroupDoc>> groups = new HashMap<BytesRef, List<GroupDoc>>();
             List<BytesRef> sortedGroups = new List<BytesRef>();
             List<IComparable[]> sortedGroupFields = new List<IComparable[]>();
@@ -591,7 +600,16 @@ namespace Lucene.Net.Search.Grouping
                 BytesRef group = sortedGroups[idx];
                 List<GroupDoc> docs = groups[group];
                 totalGroupedHitCount += docs.size();
-                docs.Sort(docSortComp);
+
+                // LUCENENET TODO: The original API Collections.Sort does not currently exist.
+                // This call ultimately results in calling TimSort, which is why this line was replaced
+                // with CollectionUtil.TimSort(IList<T>, IComparer<T>).
+                //
+                // NOTE: List.Sort(comparer) won't work in this case because it calls the comparer when the
+                // values are the same, which results in this test failing. TimSort only calls the comparer
+                // when the values differ.
+                //Collections.Sort(docs, docSortComp);
+                CollectionUtil.TimSort(docs, docSortComp);
                 ScoreDoc[] hits;
                 if (docs.size() > docOffset)
                 {


[04/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/SupportClasses.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/SupportClasses.cs b/src/Lucene.Net.Tests/core/Support/C5/SupportClasses.cs
new file mode 100644
index 0000000..8156405
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/SupportClasses.cs
@@ -0,0 +1,506 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using Lucene.Net.Support.C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace Lucene.Net.Support
+{
+    class SC : SCG.IComparer<string>
+    {
+        public int Compare(string a, string b)
+        {
+            return a.CompareTo(b);
+        }
+
+
+        public void appl(String s)
+        {
+            System.Console.WriteLine("--{0}", s);
+        }
+    }
+
+    /// <summary>
+    /// Base memory type. This abstract class is necessary for every unit test that needs to test all memory types.
+    /// </summary>
+    public abstract class BaseMemoryType
+    {
+        protected MemoryType MemoryType;
+
+        protected BaseMemoryType(MemoryType memoryType)
+        {
+            MemoryType = memoryType;
+        }
+    }
+
+    class TenEqualityComparer : SCG.IEqualityComparer<int>, SCG.IComparer<int>
+    {
+        TenEqualityComparer() { }
+        public static TenEqualityComparer Default { get { return new TenEqualityComparer(); } }
+        public int GetHashCode(int item) { return (item / 10).GetHashCode(); }
+        public bool Equals(int item1, int item2) { return item1 / 10 == item2 / 10; }
+        public int Compare(int a, int b) { return (a / 10).CompareTo(b / 10); }
+    }
+
+    class IC : SCG.IComparer<int>, IComparable<int>, SCG.IComparer<IC>, IComparable<IC>
+    {
+        public int Compare(int a, int b)
+        {
+            return a > b ? 1 : a < b ? -1 : 0;
+        }
+
+
+        public int Compare(IC a, IC b)
+        {
+            return a._i > b._i ? 1 : a._i < b._i ? -1 : 0;
+        }
+
+
+        private int _i;
+
+
+        public int i
+        {
+            get { return _i; }
+            set { _i = value; }
+        }
+
+
+        public IC() { }
+
+
+        public IC(int i) { _i = i; }
+
+
+        public int CompareTo(int that) { return _i > that ? 1 : _i < that ? -1 : 0; }
+
+        public bool Equals(int that) { return _i == that; }
+
+
+        public int CompareTo(IC that) { return _i > that._i ? 1 : _i < that._i ? -1 : 0; }
+        public bool Equals(IC that) { return _i == that._i; }
+
+
+        public static bool eq(SCG.IEnumerable<int> me, params int[] that)
+        {
+            int i = 0, maxind = that.Length - 1;
+
+            foreach (int item in me)
+                if (i > maxind || item != that[i++])
+                    return false;
+
+            return i == maxind + 1;
+        }
+        public static bool seteq(ICollectionValue<int> me, params int[] that)
+        {
+            int[] me2 = me.ToArray();
+
+            Array.Sort(me2);
+
+            int i = 0, maxind = that.Length - 1;
+
+            foreach (int item in me2)
+                if (i > maxind || item != that[i++])
+                    return false;
+
+            return i == maxind + 1;
+        }
+        public static bool seteq(ICollectionValue<KeyValuePair<int, int>> me, params int[] that)
+        {
+            ArrayList<KeyValuePair<int, int>> first = new ArrayList<KeyValuePair<int, int>>();
+            first.AddAll(me);
+            ArrayList<KeyValuePair<int, int>> other = new ArrayList<KeyValuePair<int, int>>();
+            for (int i = 0; i < that.Length; i += 2)
+            {
+                other.Add(new KeyValuePair<int, int>(that[i], that[i + 1]));
+            }
+            return other.UnsequencedEquals(first);
+        }
+    }
+
+    class RevIC : SCG.IComparer<int>
+    {
+        public int Compare(int a, int b)
+        {
+            return a > b ? -1 : a < b ? 1 : 0;
+        }
+    }
+
+    public class FunEnumerable : SCG.IEnumerable<int>
+    {
+        int size;
+        Func<int, int> f;
+
+        public FunEnumerable(int size, Func<int, int> f)
+        {
+            this.size = size; this.f = f;
+        }
+
+        public SCG.IEnumerator<int> GetEnumerator()
+        {
+            for (int i = 0; i < size; i++)
+                yield return f(i);
+        }
+
+
+        #region IEnumerable Members
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            throw new NotImplementedException();
+        }
+
+        #endregion
+    }
+
+    public class BadEnumerableException : Exception { }
+
+    public class BadEnumerable<T> : CollectionValueBase<T>, ICollectionValue<T>
+    {
+        T[] contents;
+        Exception exception;
+
+        public BadEnumerable(Exception exception, params T[] contents)
+        {
+            this.contents = (T[])contents.Clone();
+            this.exception = exception;
+        }
+
+        public override SCG.IEnumerator<T> GetEnumerator()
+        {
+            for (int i = 0; i < contents.Length; i++)
+                yield return contents[i];
+            throw exception;
+        }
+
+        public override bool IsEmpty { get { return false; } }
+
+        public override int Count { get { return contents.Length + 1; } }
+
+        public override Speed CountSpeed { get { return Speed.Constant; } }
+
+        public override T Choose() { throw exception; }
+    }
+
+    public class CollectionEventList<T>
+    {
+        ArrayList<CollectionEvent<T>> happened;
+        EventTypeEnum listenTo;
+        SCG.IEqualityComparer<T> itemequalityComparer;
+        public CollectionEventList(SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType)
+        {
+            happened = new ArrayList<CollectionEvent<T>>(memoryType);
+            this.itemequalityComparer = itemequalityComparer;
+        }
+        public void Listen(ICollectionValue<T> list, EventTypeEnum listenTo)
+        {
+            this.listenTo = listenTo;
+            if ((listenTo & EventTypeEnum.Changed) != 0)
+                list.CollectionChanged += new CollectionChangedHandler<T>(changed);
+            if ((listenTo & EventTypeEnum.Cleared) != 0)
+                list.CollectionCleared += new CollectionClearedHandler<T>(cleared);
+            if ((listenTo & EventTypeEnum.Removed) != 0)
+                list.ItemsRemoved += new ItemsRemovedHandler<T>(removed);
+            if ((listenTo & EventTypeEnum.Added) != 0)
+                list.ItemsAdded += new ItemsAddedHandler<T>(added);
+            if ((listenTo & EventTypeEnum.Inserted) != 0)
+                list.ItemInserted += new ItemInsertedHandler<T>(inserted);
+            if ((listenTo & EventTypeEnum.RemovedAt) != 0)
+                list.ItemRemovedAt += new ItemRemovedAtHandler<T>(removedAt);
+        }
+        public void Add(CollectionEvent<T> e) { happened.Add(e); }
+        /// <summary>
+        /// Check that we have seen exactly the events in expected that match listenTo.
+        /// </summary>
+        /// <param name="expected"></param>
+        public void Check(SCG.IEnumerable<CollectionEvent<T>> expected)
+        {
+            int i = 0;
+            foreach (CollectionEvent<T> expectedEvent in expected)
+            {
+                if ((expectedEvent.Act & listenTo) == 0)
+                    continue;
+                if (i >= happened.Count)
+                    Assert.Fail(string.Format("Event number {0} did not happen:\n expected {1}", i, expectedEvent));
+                if (!expectedEvent.Equals(happened[i], itemequalityComparer))
+                    Assert.Fail(string.Format("Event number {0}:\n expected {1}\n but saw {2}", i, expectedEvent, happened[i]));
+                i++;
+            }
+            if (i < happened.Count)
+                Assert.Fail(string.Format("Event number {0} seen but no event expected:\n {1}", i, happened[i]));
+            happened.Clear();
+        }
+        public void Clear() { happened.Clear(); }
+        public void Print(System.IO.TextWriter writer)
+        {
+            happened.Apply(delegate (CollectionEvent<T> e) { writer.WriteLine(e); });
+        }
+        void changed(object sender)
+        {
+            happened.Add(new CollectionEvent<T>(EventTypeEnum.Changed, new EventArgs(), sender));
+        }
+        void cleared(object sender, ClearedEventArgs eventArgs)
+        {
+            happened.Add(new CollectionEvent<T>(EventTypeEnum.Cleared, eventArgs, sender));
+        }
+        void added(object sender, ItemCountEventArgs<T> eventArgs)
+        {
+            happened.Add(new CollectionEvent<T>(EventTypeEnum.Added, eventArgs, sender));
+        }
+        void removed(object sender, ItemCountEventArgs<T> eventArgs)
+        {
+            happened.Add(new CollectionEvent<T>(EventTypeEnum.Removed, eventArgs, sender));
+        }
+        void inserted(object sender, ItemAtEventArgs<T> eventArgs)
+        {
+            happened.Add(new CollectionEvent<T>(EventTypeEnum.Inserted, eventArgs, sender));
+        }
+        void removedAt(object sender, ItemAtEventArgs<T> eventArgs)
+        {
+            happened.Add(new CollectionEvent<T>(EventTypeEnum.RemovedAt, eventArgs, sender));
+        }
+    }
+
+    public sealed class CollectionEvent<T>
+    {
+        public readonly EventTypeEnum Act;
+        public readonly EventArgs Args;
+        public readonly object Sender;
+
+        public CollectionEvent(EventTypeEnum act, EventArgs args, object sender)
+        {
+            this.Act = act;
+            this.Args = args;
+            this.Sender = sender;
+        }
+
+        public bool Equals(CollectionEvent<T> otherEvent, SCG.IEqualityComparer<T> itemequalityComparer)
+        {
+            if (otherEvent == null || Act != otherEvent.Act || !object.ReferenceEquals(Sender, otherEvent.Sender))
+                return false;
+            switch (Act)
+            {
+                case EventTypeEnum.None:
+                    break;
+                case EventTypeEnum.Changed:
+                    return true;
+                case EventTypeEnum.Cleared:
+                    if (Args is ClearedRangeEventArgs)
+                    {
+                        ClearedRangeEventArgs a = Args as ClearedRangeEventArgs, o = otherEvent.Args as ClearedRangeEventArgs;
+                        if (o == null)
+                            return false;
+                        return a.Full == o.Full && a.Start == o.Start && a.Count == o.Count;
+                    }
+                    else
+                    {
+                        if (otherEvent.Args is ClearedRangeEventArgs)
+                            return false;
+                        ClearedEventArgs a = Args as ClearedEventArgs, o = otherEvent.Args as ClearedEventArgs;
+                        return a.Full == o.Full && a.Count == o.Count;
+                    }
+                case EventTypeEnum.Added:
+                    {
+                        ItemCountEventArgs<T> a = Args as ItemCountEventArgs<T>, o = otherEvent.Args as ItemCountEventArgs<T>;
+                        return itemequalityComparer.Equals(a.Item, o.Item) && a.Count == o.Count;
+                    }
+                case EventTypeEnum.Removed:
+                    {
+                        ItemCountEventArgs<T> a = Args as ItemCountEventArgs<T>, o = otherEvent.Args as ItemCountEventArgs<T>;
+                        return itemequalityComparer.Equals(a.Item, o.Item) && a.Count == o.Count;
+                    }
+                case EventTypeEnum.Inserted:
+                    {
+                        ItemAtEventArgs<T> a = Args as ItemAtEventArgs<T>, o = otherEvent.Args as ItemAtEventArgs<T>;
+                        return a.Index == o.Index && itemequalityComparer.Equals(a.Item, o.Item);
+                    }
+                case EventTypeEnum.RemovedAt:
+                    {
+                        ItemAtEventArgs<T> a = Args as ItemAtEventArgs<T>, o = otherEvent.Args as ItemAtEventArgs<T>;
+                        return a.Index == o.Index && itemequalityComparer.Equals(a.Item, o.Item);
+                    }
+            }
+            throw new ApplicationException("Illegal Action: " + Act);
+        }
+
+        public override string ToString()
+        {
+            return string.Format("Action: {0}, Args : {1}, Source : {2}", Act, Args, Sender);
+        }
+
+    }
+
+    public class CHC
+    {
+        static public int unsequencedhashcode(params int[] a)
+        {
+            int h = 0;
+            foreach (int i in a)
+            {
+                h += (int)(((uint)i * 1529784657 + 1) ^ ((uint)i * 2912831877) ^ ((uint)i * 1118771817 + 2));
+            }
+            return h;
+        }
+        static public int sequencedhashcode(params int[] a)
+        {
+            int h = 0;
+            foreach (int i in a) { h = h * 31 + i; }
+            return h;
+        }
+    }
+
+    //This class is a modified sample from VS2005 beta1 documentation
+    public class RadixFormatProvider : IFormatProvider
+    {
+        RadixFormatter _radixformatter;
+        public RadixFormatProvider(int radix)
+        {
+            if (radix < 2 || radix > 36)
+                throw new ArgumentException(string.Format(
+                    "The radix \"{0}\" is not in the range 2..36.",
+                    radix));
+            _radixformatter = new RadixFormatter(radix);
+        }
+        public object GetFormat(Type argType)
+        {
+            if (argType == typeof(ICustomFormatter))
+                return _radixformatter;
+            else
+                return null;
+        }
+    }
+
+    //This class is a modified sample from VS2005 beta1 documentation
+    public class RadixFormatter : ICustomFormatter
+    {
+        int radix;
+        public RadixFormatter(int radix)
+        {
+            if (radix < 2 || radix > 36)
+                throw new ArgumentException(string.Format(
+                    "The radix \"{0}\" is not in the range 2..36.",
+                    radix));
+            this.radix = radix;
+        }
+
+        // The value to be formatted is returned as a signed string 
+        // of digits from the rDigits array. 
+        private static char[] rDigits = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+        'U', 'V', 'W', 'X', 'Y', 'Z' };
+
+        public string Format(string formatString,
+            object argToBeFormatted, IFormatProvider provider)
+        {
+            /*switch (Type.GetTypeCode(argToBeFormatted.GetType()))
+            {
+              case TypeCode.Boolean:
+                break;
+              case TypeCode.Byte:
+                break;
+              case TypeCode.Char:
+                break;
+              case TypeCode.DBNull:
+                break;
+              case TypeCode.DateTime:
+                break;
+              case TypeCode.Decimal:
+                break;
+              case TypeCode.Double:
+                break;
+              case TypeCode.Empty:
+                break;
+              case TypeCode.Int16:
+                break;
+              case TypeCode.Int32:
+                break;
+              case TypeCode.Int64:
+                break;
+              case TypeCode.Object:
+                break;
+              case TypeCode.SByte:
+                break;
+              case TypeCode.Single:
+                break;
+              case TypeCode.String:
+                break;
+              case TypeCode.UInt16:
+                break;
+              case TypeCode.UInt32:
+                break;
+              case TypeCode.UInt64:
+                break;
+            }*/
+            int intToBeFormatted;
+            try
+            {
+                intToBeFormatted = (int)argToBeFormatted;
+            }
+            catch (Exception)
+            {
+                if (argToBeFormatted is IFormattable)
+                    return ((IFormattable)argToBeFormatted).
+                        ToString(formatString, provider);
+                else
+                    return argToBeFormatted.ToString();
+            }
+            return formatInt(intToBeFormatted);
+        }
+
+        private string formatInt(int intToBeFormatted)
+        {
+            // The formatting is handled here.
+            if (intToBeFormatted == 0)
+                return "0";
+            int digitIndex = 0;
+            int intPositive;
+            char[] outDigits = new char[31];
+
+            // Verify that the argument can be converted to a int integer.
+            // Extract the magnitude for conversion.
+            intPositive = Math.Abs(intToBeFormatted);
+
+            // Convert the magnitude to a digit string.
+            for (digitIndex = 0; digitIndex <= 32; digitIndex++)
+            {
+                if (intPositive == 0) break;
+
+                outDigits[outDigits.Length - digitIndex - 1] =
+                    rDigits[intPositive % radix];
+                intPositive /= radix;
+            }
+
+            // Add a minus sign if the argument is negative.
+            if (intToBeFormatted < 0)
+                outDigits[outDigits.Length - digitIndex++ - 1] =
+                    '-';
+
+            return new string(outDigits,
+                outDigits.Length - digitIndex, digitIndex);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/WeakViewList.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/WeakViewList.cs b/src/Lucene.Net.Tests/core/Support/C5/WeakViewList.cs
new file mode 100644
index 0000000..4861115
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/WeakViewList.cs
@@ -0,0 +1,101 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.C5
+{
+    /// <summary>
+    /// Characterize the mutual position of some view B (other) relative to view A (this)
+    /// </summary>
+    enum MutualViewPosition
+    {
+        /// <summary>
+        /// B contains A(this)
+        /// </summary>
+        Contains,
+        /// <summary>
+        /// B is containd in A(this), but not vice versa
+        /// </summary>
+        ContainedIn,
+        /// <summary>
+        /// A and B does not overlap
+        /// </summary>
+        NonOverlapping,
+        /// <summary>
+        /// A and B overlap, but neither is contained in the other
+        /// </summary>
+        Overlapping
+    }
+
+    #region View List Nested class
+    /// <summary>
+    /// This class is shared between the linked list and array list implementations.
+    /// </summary>
+    /// <typeparam name="V"></typeparam>
+    [Serializable]
+    class WeakViewList<V> where V : class
+    {
+        Node start;
+
+        [Serializable]
+        internal class Node
+        {
+            internal WeakReference weakview; internal Node prev, next;
+            internal Node(V view) { weakview = new WeakReference(view); }
+        }
+        internal Node Add(V view)
+        {
+            Node newNode = new Node(view);
+            if (start != null) { start.prev = newNode; newNode.next = start; }
+            start = newNode;
+            return newNode;
+        }
+        internal void Remove(Node n)
+        {
+            if (n == start) { start = start.next; if (start != null) start.prev = null; }
+            else { n.prev.next = n.next; if (n.next != null) n.next.prev = n.prev; }
+        }
+        /// <summary>
+        /// Note that it is safe to call views.Remove(view.myWeakReference) if view
+        /// is the currently yielded object
+        /// </summary>
+        /// <returns></returns>
+        public SCG.IEnumerator<V> GetEnumerator()
+        {
+            Node n = start;
+            while (n != null)
+            {
+                //V view = n.weakview.Target as V; //This provokes a bug in the beta1 verifyer
+                object o = n.weakview.Target;
+                V view = o is V ? (V)o : null;
+                if (view == null)
+                    Remove(n);
+                else
+                    yield return view;
+                n = n.next;
+            }
+        }
+    }
+
+    #endregion
+}


[47/58] [abbrv] lucenenet git commit: Removed superfluous IGroupCount interface. Created non-generic AbstractDistinctValuesCollector class to nest IGroupCount and GroupCount so the syntax is similar to Lucene.

Posted by ni...@apache.org.
Removed superfluous IGroupCount interface. Created non-generic AbstractDistinctValuesCollector class to nest IGroupCount and GroupCount so the syntax is similar to Lucene.


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

Branch: refs/heads/grouping
Commit: 41b9732e9a11f3ad04f8633ce47857c7c98e18e0
Parents: 95bb669
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 22:19:37 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:58 2016 +0700

----------------------------------------------------------------------
 .../AbstractDistinctValuesCollector.cs          | 93 ++++++++------------
 .../Function/FunctionDistinctValuesCollector.cs |  2 +-
 .../Term/TermDistinctValuesCollector.cs         |  2 +-
 .../DistinctValuesCollectorTest.cs              | 36 ++++----
 4 files changed, 56 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/41b9732e/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
index 0f51a24..5c3e624 100644
--- a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
@@ -14,7 +14,7 @@ namespace Lucene.Net.Search.Grouping
     /// </summary>
     /// <typeparam name="GC"></typeparam>
     public abstract class AbstractDistinctValuesCollector<GC> : Collector, IAbstractDistinctValuesCollector<GC>
-        where GC : IGroupCount /* AbstractDistinctValuesCollector<GC>.GroupCount */
+        where GC : AbstractDistinctValuesCollector.IGroupCount<object>
     {
         /// <summary>
         /// Returns all unique values for each top N group.
@@ -35,71 +35,50 @@ namespace Lucene.Net.Search.Grouping
         } 
     }
 
-    //public abstract class AbstractDistinctValuesCollector : Collector
-    //{
-    //    /// <summary>
-    //    /// Returns all unique values for each top N group.
-    //    /// </summary>
-    //    /// <returns>all unique values for each top N group</returns>
-    //    public abstract List<GC> GetGroups();
-
-    //    public override bool AcceptsDocsOutOfOrder()
-    //    {
-    //        return true;
-    //    }
-
-    //    public override Scorer Scorer
-    //    {
-    //        set
-    //        {
-    //        }
-    //    }
-    //}
-
-
     /// <summary>
-    /// Returned by <see cref="AbstractDistinctValuesCollector.GetGroups()"/>,
-    /// representing the value and set of distinct values for the group.
+    /// LUCENENET specific class used to nest the <see cref="GroupCount{TGroupValue}"/>
+    /// class so it has similar syntax to that in Java Lucene
+    /// (AbstractDistinctValuesCollector.GroupCount{TGroupValue} rather than 
+    /// AbstractDistinctValuesCollector{GC}.GroupCount{TGroupValue}).
     /// </summary>
-    /// <typeparam name="TGroupValue"></typeparam>
-    /// <remarks>
-    /// LUCENENET - removed this class from being a nested class of 
-    /// <see cref="AbstractDistinctValuesCollector{GC}"/> and renamed
-    /// from GroupCount to AbstractGroupCount
-    /// </remarks>
-    public abstract class AbstractGroupCount<TGroupValue> : IGroupCount<TGroupValue>
-        //where TGroupValue : IComparable
+    public class AbstractDistinctValuesCollector
     {
-        public TGroupValue GroupValue { get; protected set; }
-        public IEnumerable<TGroupValue> UniqueValues { get; protected set; }
+        // Disallow direct creation
+        private AbstractDistinctValuesCollector() { }
 
-        public AbstractGroupCount(TGroupValue groupValue)
+        /// <summary>
+        /// Returned by <see cref="AbstractDistinctValuesCollector.GetGroups()"/>,
+        /// representing the value and set of distinct values for the group.
+        /// </summary>
+        /// <typeparam name="TGroupValue"></typeparam>
+        /// <remarks>
+        /// LUCENENET - removed this class from being a nested class of 
+        /// <see cref="AbstractDistinctValuesCollector{GC}"/> and renamed
+        /// from GroupCount to AbstractGroupCount
+        /// </remarks>
+        public abstract class GroupCount<TGroupValue> : IGroupCount<TGroupValue>
         {
-            this.GroupValue = groupValue;
-            this.UniqueValues = new HashSet<TGroupValue>();
-        }
-    }
-
-    /// <summary>
-    /// LUCENENET specific interface to allow usage of <see cref="AbstractGroupCount{TGroupValue}"/>
-    /// as a generic closing type without having to specify TGroupValue.
-    /// </summary>
-    public interface IGroupCount
-    {
-    }
+            public TGroupValue GroupValue { get; protected set; }
+            public IEnumerable<TGroupValue> UniqueValues { get; protected set; }
 
+            public GroupCount(TGroupValue groupValue)
+            {
+                this.GroupValue = groupValue;
+                this.UniqueValues = new HashSet<TGroupValue>();
+            }
+        }
 
-    /// <summary>
-    /// LUCENENET specific interface used to apply covariance to TGroupValue
-    /// </summary>
-    /// <typeparam name="TGroupValue"></typeparam>
-    public interface IGroupCount<out TGroupValue> : IGroupCount
-    {
-        TGroupValue GroupValue { get; }
-        IEnumerable<TGroupValue> UniqueValues { get; }
+        /// <summary>
+        /// LUCENENET specific interface used to apply covariance to TGroupValue
+        /// </summary>
+        /// <typeparam name="TGroupValue"></typeparam>
+        public interface IGroupCount<out TGroupValue>
+        {
+            TGroupValue GroupValue { get; }
+            IEnumerable<TGroupValue> UniqueValues { get; }
+        }
     }
 
-
     /// <summary>
     /// LUCENENET specific interface used to apply covariance to GC
     /// </summary>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/41b9732e/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
index 2d5b9ee..22f2395 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
@@ -70,7 +70,7 @@ namespace Lucene.Net.Search.Grouping.Function
         /** Holds distinct values for a single group.
          *
          * @lucene.experimental */
-        public class GroupCount : AbstractGroupCount<MutableValue> /*AbstractDistinctValuesCollector.GroupCount<MutableValue>*/
+        public class GroupCount : AbstractDistinctValuesCollector.GroupCount<MutableValue>
         {
             internal GroupCount(MutableValue groupValue)
                 : base(groupValue)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/41b9732e/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
index ac4d4e9..91bc674 100644
--- a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
@@ -129,7 +129,7 @@ namespace Lucene.Net.Search.Grouping.Terms
         /** Holds distinct values for a single group.
          *
          * @lucene.experimental */
-        public class GroupCount : AbstractGroupCount<BytesRef> /*AbstractDistinctValuesCollector.GroupCount<BytesRef>*/
+        public class GroupCount : AbstractDistinctValuesCollector.GroupCount<BytesRef>
         {
             internal int[] ords;
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/41b9732e/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
index 24beb86..711f339 100644
--- a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
@@ -26,7 +26,7 @@ namespace Lucene.Net.Search.Grouping
         private readonly string countField = "publisher";
         private readonly string dvCountField = "publisher_dv";
 
-        internal class ComparerAnonymousHelper1 : IComparer<IGroupCount<IComparable>>
+        internal class ComparerAnonymousHelper1 : IComparer<AbstractDistinctValuesCollector.IGroupCount<IComparable>>
         {
             private readonly DistinctValuesCollectorTest outerInstance;
 
@@ -35,7 +35,7 @@ namespace Lucene.Net.Search.Grouping
                 this.outerInstance = outerInstance;
             }
 
-            public int Compare(IGroupCount<IComparable> groupCount1, IGroupCount<IComparable> groupCount2)
+            public int Compare(AbstractDistinctValuesCollector.IGroupCount<IComparable> groupCount1, AbstractDistinctValuesCollector.IGroupCount<IComparable> groupCount2)
             {
                 if (groupCount1.GroupValue == null)
                 {
@@ -138,7 +138,7 @@ namespace Lucene.Net.Search.Grouping
             // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
             // so this cast is not necessary. Consider eliminating the Collector abstract class.
             indexSearcher.Search(new TermQuery(new Term("content", "random")), firstCollector as Collector);
-            IAbstractDistinctValuesCollector<IGroupCount<IComparable>> distinctValuesCollector
+            IAbstractDistinctValuesCollector<AbstractDistinctValuesCollector.IGroupCount<IComparable>> distinctValuesCollector
                 = CreateDistinctCountCollector(firstCollector, groupField, countField, dvType.GetValueOrDefault());
             // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
             // so this cast is not necessary. Consider eliminating the Collector abstract class.
@@ -146,7 +146,7 @@ namespace Lucene.Net.Search.Grouping
 
             //var gcs = distinctValuesCollector.Groups as List<IGroupCount<IComparable>>;
             // LUCENENET TODO: Try to work out how to do this without an O(n) operation
-            var gcs = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
+            var gcs = new List<AbstractDistinctValuesCollector.IGroupCount<IComparable>>(distinctValuesCollector.Groups);
             gcs.Sort(cmp);
             assertEquals(4, gcs.Count);
 
@@ -184,7 +184,7 @@ namespace Lucene.Net.Search.Grouping
 
             // LUCENENET TODO: Try to work out how to do this without an O(n) operation
             //gcs = distinctValuesCollector.Groups as List<IGroupCount<IComparable>>;
-            gcs = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
+            gcs = new List<AbstractDistinctValuesCollector.IGroupCount<IComparable>>(distinctValuesCollector.Groups);
             gcs.Sort(cmp);
             assertEquals(3, gcs.Count);
 
@@ -217,7 +217,7 @@ namespace Lucene.Net.Search.Grouping
 
             // LUCENENET TODO: Try to work out how to do this without an O(n) operation
             //gcs = distinctValuesCollector.Groups as List<IGroupCount<IComparable>>;
-            gcs = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
+            gcs = new List<AbstractDistinctValuesCollector.IGroupCount<IComparable>>(distinctValuesCollector.Groups);
             gcs.Sort(cmp);
             assertEquals(2, gcs.Count);
 
@@ -253,20 +253,20 @@ namespace Lucene.Net.Search.Grouping
                     Sort groupSort = new Sort(new SortField("id", SortField.Type_e.STRING));
                     int topN = 1 + random.nextInt(10);
 
-                    List<IGroupCount<IComparable>> expectedResult = CreateExpectedResult(context, term, groupSort, topN);
+                    List<AbstractDistinctValuesCollector.IGroupCount<IComparable>> expectedResult = CreateExpectedResult(context, term, groupSort, topN);
 
                     IAbstractFirstPassGroupingCollector<IComparable> firstCollector = CreateRandomFirstPassCollector(dvType, groupSort, groupField, topN);
                     // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
                     // so this cast is not necessary. Consider eliminating the Collector abstract class.
                     searcher.Search(new TermQuery(new Term("content", term)), firstCollector as Collector);
-                    IAbstractDistinctValuesCollector<IGroupCount<IComparable>> distinctValuesCollector
+                    IAbstractDistinctValuesCollector<AbstractDistinctValuesCollector.IGroupCount<IComparable>> distinctValuesCollector
                         = CreateDistinctCountCollector(firstCollector, groupField, countField, dvType);
                     // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
                     // so this cast is not necessary. Consider eliminating the Collector abstract class.
                     searcher.Search(new TermQuery(new Term("content", term)), distinctValuesCollector as Collector);
 
                     // LUCENENET TODO: Try to work out how to do this without an O(n) operation
-                    List<IGroupCount<IComparable>> actualResult = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
+                    List<AbstractDistinctValuesCollector.IGroupCount<IComparable>> actualResult = new List<AbstractDistinctValuesCollector.IGroupCount<IComparable>>(distinctValuesCollector.Groups);
 
                     if (VERBOSE)
                     {
@@ -287,8 +287,8 @@ namespace Lucene.Net.Search.Grouping
                     assertEquals(expectedResult.Count, actualResult.Count);
                     for (int i = 0; i < expectedResult.size(); i++)
                     {
-                        IGroupCount<IComparable> expected = expectedResult[i];
-                        IGroupCount<IComparable> actual = actualResult[i];
+                        AbstractDistinctValuesCollector.IGroupCount<IComparable> expected = expectedResult[i];
+                        AbstractDistinctValuesCollector.IGroupCount<IComparable> actual = actualResult[i];
                         AssertValues(expected.GroupValue, actual.GroupValue);
                         assertEquals(expected.UniqueValues.Count(), actual.UniqueValues.Count());
                         List<IComparable> expectedUniqueValues = new List<IComparable>(expected.UniqueValues);
@@ -306,7 +306,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void PrintGroups(List<IGroupCount<IComparable>> results)
+        private void PrintGroups(List<AbstractDistinctValuesCollector.IGroupCount<IComparable>> results)
         {
             for (int i = 0; i < results.size(); i++)
             {
@@ -427,7 +427,7 @@ namespace Lucene.Net.Search.Grouping
             doc.Add(valuesField);
         }
 
-        private IAbstractDistinctValuesCollector<IGroupCount<T>> CreateDistinctCountCollector<T>(IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
+        private IAbstractDistinctValuesCollector<AbstractDistinctValuesCollector.IGroupCount<T>> CreateDistinctCountCollector<T>(IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
                                                                             string groupField,
                                                                             string countField,
                                                                             FieldInfo.DocValuesType_e? dvType)
@@ -436,11 +436,11 @@ namespace Lucene.Net.Search.Grouping
             IEnumerable<ISearchGroup<T>> searchGroups = firstPassGroupingCollector.GetTopGroups(0, false);
             if (typeof(FunctionFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
             {
-                return (IAbstractDistinctValuesCollector<IGroupCount<T>>)new FunctionDistinctValuesCollector(new Hashtable(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), searchGroups as IEnumerable<ISearchGroup<MutableValue>>);
+                return (IAbstractDistinctValuesCollector<AbstractDistinctValuesCollector.IGroupCount<T>>)new FunctionDistinctValuesCollector(new Hashtable(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), searchGroups as IEnumerable<ISearchGroup<MutableValue>>);
             }
             else
             {
-                return (IAbstractDistinctValuesCollector<IGroupCount<T>>)new TermDistinctValuesCollector(groupField, countField, searchGroups as IEnumerable<ISearchGroup<BytesRef>>);
+                return (IAbstractDistinctValuesCollector<AbstractDistinctValuesCollector.IGroupCount<T>>)new TermDistinctValuesCollector(groupField, countField, searchGroups as IEnumerable<ISearchGroup<BytesRef>>);
             }
         }
 
@@ -475,7 +475,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        internal class GroupCount : AbstractGroupCount<BytesRef>
+        internal class GroupCount : AbstractDistinctValuesCollector.GroupCount<BytesRef>
         {
             internal GroupCount(BytesRef groupValue, IEnumerable<BytesRef> uniqueValues)
                 : base(groupValue)
@@ -484,9 +484,9 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private List<IGroupCount<IComparable>> CreateExpectedResult(IndexContext context, string term, Sort groupSort, int topN)
+        private List<AbstractDistinctValuesCollector.IGroupCount<IComparable>> CreateExpectedResult(IndexContext context, string term, Sort groupSort, int topN)
         {
-            List<IGroupCount<IComparable>> result = new List<IGroupCount<IComparable>>();
+            List<AbstractDistinctValuesCollector.IGroupCount<IComparable>> result = new List<AbstractDistinctValuesCollector.IGroupCount<IComparable>>();
             IDictionary<string, ISet<string>> groupCounts = context.searchTermToGroupCounts[term];
             int i = 0;
             foreach (string group in groupCounts.Keys)


[07/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/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 3664713..e9e98e8 100644
--- a/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
+++ b/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
@@ -473,12 +473,24 @@
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="core\Support\BaseBufferTestCase.cs" />
+    <Compile Include="core\Support\C5\ArrayBase.cs" />
+    <Compile Include="core\Support\C5\ArrayList.cs" />
+    <Compile Include="core\Support\C5\DropMultiplicity.cs" />
+    <Compile Include="core\Support\C5\Events.cs" />
+    <Compile Include="core\Support\C5\GenericCollectionTester.cs" />
+    <Compile Include="core\Support\C5\HashBag.cs" />
+    <Compile Include="core\Support\C5\Sorting.cs" />
+    <Compile Include="core\Support\C5\SupportClasses.cs" />
+    <Compile Include="core\Support\C5\WeakViewList.cs" />
+    <Compile Include="core\Support\C5\Wrappers.cs" />
     <Compile Include="core\Support\TestLongBuffer.cs" />
     <Compile Include="core\Support\TestByteBuffer.cs" />
     <Compile Include="core\Support\TestLurchTable.cs" />
     <Compile Include="core\Support\TestLurchTableThreading.cs" />
     <Compile Include="core\Support\TestDataInputStream.cs" />
     <Compile Include="core\Support\TestDataOutputStream.cs" />
+    <Compile Include="core\Support\TestTreeDictionary.cs" />
+    <Compile Include="core\Support\TestTreeSet.cs" />
     <Compile Include="core\TestAssertions.cs">
       <SubType>Code</SubType>
     </Compile>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/ArrayBase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/ArrayBase.cs b/src/Lucene.Net.Tests/core/Support/C5/ArrayBase.cs
new file mode 100644
index 0000000..7a8f5eb
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/ArrayBase.cs
@@ -0,0 +1,479 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.C5
+{
+    /// <summary>
+    /// Base class for collection classes of dynamic array type implementations.
+    /// </summary>
+    [Serializable]
+    public abstract class ArrayBase<T> : SequencedBase<T>
+    {
+        #region Fields
+        /// <summary>
+        /// The actual internal array container. Will be extended on demand.
+        /// </summary>
+        protected T[] array;
+
+        /// <summary>
+        /// The offset into the internal array container of the first item. The offset is 0 for a 
+        /// base dynamic array and may be positive for an updatable view into a base dynamic array.
+        /// </summary>
+        protected int offsetField;
+
+        private readonly Enumerator _internalEnumerator;
+        #endregion
+
+        #region Util
+        /// <summary>
+        /// Double the size of the internal array.
+        /// </summary>
+        protected virtual void expand()
+        {
+            expand(2 * array.Length, size);
+        }
+
+
+        /// <summary>
+        /// Expand the internal array container.
+        /// </summary>
+        /// <param name="newcapacity">The new size of the internal array - 
+        /// will be rounded upwards to a power of 2.</param>
+        /// <param name="newsize">The (new) size of the (base) collection.</param>
+        protected virtual void expand(int newcapacity, int newsize)
+        {
+            System.Diagnostics.Debug.Assert(newcapacity >= newsize);
+
+            int newlength = array.Length;
+
+            while (newlength < newcapacity) newlength *= 2;
+
+            T[] newarray = new T[newlength];
+
+            Array.Copy(array, newarray, newsize);
+            array = newarray;
+        }
+
+
+        /// <summary>
+        /// Insert an item at a specific index, moving items to the right
+        /// upwards and expanding the array if necessary.
+        /// </summary>
+        /// <param name="i">The index at which to insert.</param>
+        /// <param name="item">The item to insert.</param>
+        protected virtual void InsertProtected(int i, T item)
+        {
+            if (size == array.Length)
+                expand();
+
+            if (i < size)
+                Array.Copy(array, i, array, i + 1, size - i);
+
+            array[i] = item;
+            size++;
+        }
+
+        #endregion
+
+        #region Constructors
+
+        /// <summary>
+        /// Create an empty ArrayBase object.
+        /// </summary>
+        /// <param name="capacity">The initial capacity of the internal array container.
+        /// Will be rounded upwards to the nearest power of 2 greater than or equal to 8.</param>
+        /// <param name="itemequalityComparer">The item equalityComparer to use, primarily for item equality</param>
+        /// <param name="memoryType">The type of memory for the enumerator used to iterate the collection</param>
+        protected ArrayBase(int capacity, SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType)
+            : base(itemequalityComparer, memoryType)
+        {
+            int newlength = 8;
+            while (newlength < capacity) newlength *= 2;
+            array = new T[newlength];
+
+            _internalEnumerator = new Enumerator(this, memoryType);
+        }
+
+
+
+        #endregion
+
+        #region IIndexed members
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException">If the arguments does not describe a 
+        /// valid range in the indexed collection, cf. <see cref="M:C5.CollectionBase`1.checkRange(System.Int32,System.Int32)"/>.</exception>
+        /// <value>The directed collection of items in a specific index interval.</value>
+        /// <param name="start">The low index of the interval (inclusive).</param>
+        /// <param name="count">The size of the range.</param>
+        public virtual IDirectedCollectionValue<T> this[int start, int count]
+        {
+            get
+            {
+                checkRange(start, count);
+                return new Range(this, start, count, true);
+            }
+        }
+
+        #endregion
+
+        #region IEditableCollection members
+        /// <summary>
+        /// Remove all items and reset size of internal array container.
+        /// </summary>
+        public virtual void Clear()
+        {
+            updatecheck();
+            array = new T[8];
+            size = 0;
+        }
+
+
+        /// <summary>
+        /// Create an array containing (copies) of the items of this collection in enumeration order.
+        /// </summary>
+        /// <returns>The new array</returns>
+        public override T[] ToArray()
+        {
+            T[] res = new T[size];
+
+            Array.Copy(array, offsetField, res, 0, size);
+            return res;
+        }
+
+
+        /// <summary>
+        /// Perform an internal consistency (invariant) test on the array base.
+        /// </summary>
+        /// <returns>True if test succeeds.</returns>
+        public virtual bool Check()
+        {
+            bool retval = true;
+
+            if (size > array.Length)
+            {
+                Logger.Log(string.Format("Bad size ({0}) > array.Length ({1})", size, array.Length));
+                return false;
+            }
+
+            for (int i = 0; i < size; i++)
+            {
+                if ((object)(array[i]) == null)
+                {
+                    Logger.Log(string.Format("Bad element: null at index {0}", i));
+                    return false;
+                }
+            }
+
+            return retval;
+        }
+
+        #endregion
+
+        #region IDirectedCollection<T> Members
+
+        /// <summary>
+        /// Create a directed collection with the same contents as this one, but 
+        /// opposite enumeration sequence.
+        /// </summary>
+        /// <returns>The mirrored collection.</returns>
+        public override IDirectedCollectionValue<T> Backwards() { return this[0, size].Backwards(); }
+
+        #endregion
+
+        /// <summary>
+        /// Choose some item of this collection. The result is the last item in the internal array,
+        /// making it efficient to remove.
+        /// </summary>
+        /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+        /// <returns></returns>
+        public override T Choose() { if (size > 0) return array[size - 1]; throw new NoSuchItemException(); }
+
+
+        #region Private Enumerator
+
+        [Serializable]
+        private class Enumerator : MemorySafeEnumerator<T>
+        {
+            private ArrayBase<T> _internalList;
+
+            private int _internalIncrementalIndex;
+            private int _theStamp;
+            private int _end;
+
+
+
+            public Enumerator(ArrayBase<T> list, MemoryType memoryType)
+                : base(memoryType)
+            {
+                _internalList = list;
+
+            }
+
+            internal void UpdateReference(ArrayBase<T> list, int start, int end, int theStamp)
+            {
+                _internalIncrementalIndex = start;
+                _end = end;
+                _internalList = list;
+                Current = default(T);
+                _theStamp = theStamp;
+            }
+
+
+            public override bool MoveNext()
+            {
+                ArrayBase<T> list = _internalList;
+
+                if (list.stamp != _theStamp)
+                    throw new CollectionModifiedException();
+
+                if (_internalIncrementalIndex < _end)
+                {
+                    Current = list.array[_internalIncrementalIndex];
+                    _internalIncrementalIndex++;
+
+                    return true;
+                }
+
+                Current = default(T);
+                return false;
+            }
+
+            public override void Reset()
+            {
+                _internalIncrementalIndex = 0;
+                Current = default(T);
+            }
+
+
+            protected override MemorySafeEnumerator<T> Clone()
+            {
+                var enumerator = new Enumerator(_internalList, MemoryType)
+                {
+                    Current = default(T),
+
+                };
+                return enumerator;
+            }
+        }
+        #endregion
+        #region IEnumerable<T> Members
+        /// <summary>
+        /// Create an enumerator for this array based collection.
+        /// </summary>
+        /// <returns>The enumerator</returns>
+        public override SCG.IEnumerator<T> GetEnumerator()
+        {
+            int thestamp = stamp, theend = size + offsetField, thestart = offsetField;
+
+            var enumerator = (Enumerator)_internalEnumerator.GetEnumerator();
+
+            enumerator.UpdateReference(this, thestart, theend, thestamp);
+
+            return enumerator;
+        }
+        #endregion
+
+        #region Range nested class
+        /// <summary>
+        /// A helper class for defining results of interval queries on array based collections.
+        /// </summary>
+        [Serializable]
+        protected class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+        {
+            int start, count, delta, stamp;
+
+            ArrayBase<T> thebase;
+
+            private readonly RangeEnumerator _rangeInternalEnumerator;
+
+            internal Range(ArrayBase<T> thebase, int start, int count, bool forwards, MemoryType memoryType = MemoryType.Normal)
+            {
+
+                this.thebase = thebase; stamp = thebase.stamp;
+                delta = forwards ? 1 : -1;
+
+                this.start = start + thebase.offsetField; this.count = count;
+                _rangeInternalEnumerator = new RangeEnumerator(thebase, memoryType);
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <value>True if this collection is empty.</value>
+            public override bool IsEmpty { get { thebase.modifycheck(stamp); return count == 0; } }
+
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <value>The number of items in the range</value>
+            public override int Count { get { thebase.modifycheck(stamp); return count; } }
+
+            /// <summary>
+            /// The value is symbolic indicating the type of asymptotic complexity
+            /// in terms of the size of this collection (worst-case or amortized as
+            /// relevant).
+            /// </summary>
+            /// <value>A characterization of the speed of the 
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <code>Count</code> property in this collection.</value>
+            public override Speed CountSpeed { get { thebase.modifycheck(stamp); return Speed.Constant; } }
+
+            /// <summary>
+            /// Choose some item of this collection. 
+            /// </summary>
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <exception cref="NoSuchItemException">if range is empty.</exception>
+            /// <returns></returns>
+            public override T Choose()
+            {
+                thebase.modifycheck(stamp);
+                if (count == 0)
+                    throw new NoSuchItemException();
+                return thebase.array[start];
+            }
+
+
+            /// <summary>
+            /// Create an enumerator for this range of an array based collection.
+            /// </summary>
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <returns>The enumerator</returns>
+            public override SCG.IEnumerator<T> GetEnumerator()
+            {
+                var enumerator = (RangeEnumerator)_rangeInternalEnumerator.GetEnumerator();
+
+                enumerator.UpdateReference(thebase, start, delta, stamp, count);
+
+                return enumerator;
+            }
+
+
+            /// <summary>
+            /// Create an array collection range with the same contents as this one, but 
+            /// opposite enumeration sequence.
+            /// </summary>
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <returns>The mirrored collection.</returns>
+            public override IDirectedCollectionValue<T> Backwards()
+            {
+                thebase.modifycheck(stamp);
+
+                Range res = (Range)MemberwiseClone();
+
+                res.delta = -delta;
+                res.start = start + (count - 1) * delta;
+                return res;
+            }
+
+
+            IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+            {
+                return Backwards();
+            }
+
+            private sealed class RangeEnumerator : MemorySafeEnumerator<T>
+            {
+                private ArrayBase<T> _rangeEnumeratorArrayBase;
+
+                private int _start;
+                private int _count;
+                private int _theStamp;
+                private int _delta;
+                private int _index;
+
+
+                public RangeEnumerator(ArrayBase<T> internalList, MemoryType memoryType)
+                    : base(memoryType)
+                {
+                    _rangeEnumeratorArrayBase = internalList;
+                    IteratorState = -1;
+                    _index = 0;
+                }
+
+                internal void UpdateReference(ArrayBase<T> list, int start, int delta, int theStamp, int count)
+                {
+                    _count = count;
+                    _start = start;
+                    _delta = delta;
+                    _rangeEnumeratorArrayBase = list;
+                    Current = default(T);
+                    _theStamp = theStamp;
+                }
+
+
+                protected override MemorySafeEnumerator<T> Clone()
+                {
+                    var enumerator = new RangeEnumerator(_rangeEnumeratorArrayBase, MemoryType)
+                    {
+                        Current = default(T),
+
+                    };
+                    return enumerator;
+                }
+
+                public override bool MoveNext()
+                {
+                    ArrayBase<T> list = _rangeEnumeratorArrayBase;
+
+                    list.modifycheck(_theStamp);
+
+                    if (_index < _count)
+                    {
+                        Current = list.array[_start + _delta * _index];
+                        _index++;
+                        return true;
+                    }
+
+                    Current = default(T);
+                    return false;
+                }
+
+                public override void Reset()
+                {
+                    _index = 0;
+                    Current = default(T);
+                }
+            }
+
+            /// <summary>
+            /// <code>Forwards</code> if same, else <code>Backwards</code>
+            /// </summary>
+            /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+            /// <value>The enumeration direction relative to the original collection.</value>
+            public override EnumerationDirection Direction
+            {
+                get
+                {
+                    thebase.modifycheck(stamp);
+                    return delta > 0 ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;
+                }
+            }
+        }
+        #endregion
+    }
+}


[58/58] [abbrv] lucenenet git commit: Grouping: Updated member accessibility to be the same as Java Lucene.

Posted by ni...@apache.org.
Grouping: Updated member accessibility to be the same as Java Lucene.


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

Branch: refs/heads/grouping
Commit: 96d38effd9f91433a21ddcbd781eb7c0b0c3df02
Parents: 987a985
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Tue Nov 8 02:05:56 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:35 2016 +0700

----------------------------------------------------------------------
 .../AbstractFirstPassGroupingCollector.cs       |  3 +-
 .../AbstractGroupFacetCollector.cs              | 12 +++---
 .../AbstractSecondPassGroupingCollector.cs      |  2 +-
 .../BlockGroupingCollector.cs                   |  5 +--
 src/Lucene.Net.Grouping/GroupingSearch.cs       | 44 ++++++++++----------
 src/Lucene.Net.Grouping/SearchGroup.cs          |  2 +-
 6 files changed, 34 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96d38eff/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
index 62440f1..ee58899 100644
--- a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
@@ -103,7 +103,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupOffset">The offset in the collected groups</param>
         /// <param name="fillFields">Whether to fill to <see cref="SearchGroup.sortValues"/></param>
         /// <returns>top groups, starting from offset</returns>
-        public IEnumerable<ISearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields)
+        public virtual IEnumerable<ISearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields)
         {
 
             //System.out.println("FP.getTopGroups groupOffset=" + groupOffset + " fillFields=" + fillFields + " groupMap.size()=" + groupMap.size());
@@ -371,6 +371,7 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
         }
+
         private void BuildSortedSet()
         {
             var comparator = new BuildSortedSetComparer(this);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96d38eff/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
index 6e3e014..30c7bd4 100644
--- a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
@@ -57,7 +57,7 @@ namespace Lucene.Net.Search.Grouping
         /// </param>
         /// <returns>grouped facet results</returns>
         /// <exception cref="IOException">If I/O related errors occur during merging segment grouped facet counts.</exception>
-        public GroupedFacetResult MergeSegmentResults(int size, int minCount, bool orderByCount)
+        public virtual GroupedFacetResult MergeSegmentResults(int size, int minCount, bool orderByCount)
         {
             if (segmentFacetCounts != null)
             {
@@ -200,7 +200,7 @@ namespace Lucene.Net.Search.Grouping
             /// <param name="offset">The offset in the collected facet entries during merging</param>
             /// <param name="limit">The number of facets to return starting from the offset.</param>
             /// <returns>a list of facet entries to be rendered based on the specified offset and limit</returns>
-            public List<FacetEntry> GetFacetEntries(int offset, int limit)
+            public virtual List<FacetEntry> GetFacetEntries(int offset, int limit)
             {
                 List<FacetEntry> entries = new List<FacetEntry>();
 
@@ -225,7 +225,7 @@ namespace Lucene.Net.Search.Grouping
             /// <summary>
             /// Gets the sum of all facet entries counts.
             /// </summary>
-            public int TotalCount
+            public virtual int TotalCount
             {
                 get
                 {
@@ -236,7 +236,7 @@ namespace Lucene.Net.Search.Grouping
             /// <summary>
             /// Gets the number of groups that didn't have a facet value.
             /// </summary>
-            public int TotalMissingCount
+            public virtual int TotalMissingCount
             {
                 get
                 {
@@ -291,7 +291,7 @@ namespace Lucene.Net.Search.Grouping
             /// <summary>
             /// Gets the value of this facet entry
             /// </summary>
-            public BytesRef Value
+            public virtual BytesRef Value
             {
                 get
                 {
@@ -302,7 +302,7 @@ namespace Lucene.Net.Search.Grouping
             /// <summary>
             /// Gets the count (number of groups) of this facet entry.
             /// </summary>
-            public int Count
+            public virtual int Count
             {
                 get
                 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96d38eff/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
index e8aedc8..30f8c0b 100644
--- a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
@@ -129,7 +129,7 @@ namespace Lucene.Net.Search.Grouping
             return false;
         }
 
-        public ITopGroups<TGroupValue> GetTopGroups(int withinGroupOffset)
+        public virtual ITopGroups<TGroupValue> GetTopGroups(int withinGroupOffset)
         {
             GroupDocs<TGroupValue>[] groupDocsResult = new GroupDocs<TGroupValue>[groups.Count()];
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96d38eff/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
index 0f3549f..6a7afd5 100644
--- a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
@@ -132,7 +132,6 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-
             public override ICollection<ChildScorer> Children
             {
                 get
@@ -354,7 +353,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="fillSortFields">
         /// If true then the Comparable values for the sort fields will be set
         /// </param>
-        public ITopGroups<object> GetTopGroups(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
+        public virtual ITopGroups<object> GetTopGroups(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
         {
             return GetTopGroups<object>(withinGroupSort, groupOffset, withinGroupOffset, maxDocsPerGroup, fillSortFields);
         }
@@ -388,7 +387,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="fillSortFields">
         /// If true then the Comparable values for the sort fields will be set
         /// </param>
-        public ITopGroups<TGroupValue> GetTopGroups<TGroupValue>(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
+        public virtual ITopGroups<TGroupValue> GetTopGroups<TGroupValue>(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
         {
 
             //if (queueFull) {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96d38eff/src/Lucene.Net.Grouping/GroupingSearch.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupingSearch.cs b/src/Lucene.Net.Grouping/GroupingSearch.cs
index 5bb98c5..4f46f1a 100644
--- a/src/Lucene.Net.Grouping/GroupingSearch.cs
+++ b/src/Lucene.Net.Grouping/GroupingSearch.cs
@@ -105,7 +105,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
         /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
         /// <exception cref="IOException">If any I/O related errors occur</exception>
-        public ITopGroups<object> Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+        public virtual ITopGroups<object> Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
         {
             return Search<object>(searcher, null, query, groupOffset, groupLimit);
         }
@@ -121,7 +121,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
         /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
         /// <exception cref="IOException">If any I/O related errors occur</exception>
-        public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+        public virtual ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
         {
             return Search<TGroupValue>(searcher, null, query, groupOffset, groupLimit);
         }
@@ -136,7 +136,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
         /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
         /// <exception cref="IOException">If any I/O related errors occur</exception>
-        public ITopGroups<object> Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        public virtual ITopGroups<object> Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             if (groupFunction != null)
             {
@@ -167,7 +167,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
         /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
         /// <exception cref="IOException">If any I/O related errors occur</exception>
-        public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        public virtual ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             if (groupField != null || groupFunction != null)
             {
@@ -183,7 +183,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        protected ITopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        protected virtual ITopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             int topN = groupOffset + groupLimit;
             IAbstractFirstPassGroupingCollector<TGroupValue> firstPassCollector;
@@ -335,7 +335,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        protected ITopGroups<TGroupValue> GroupByDocBlock<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        protected virtual ITopGroups<TGroupValue> GroupByDocBlock<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             int topN = groupOffset + groupLimit;
             BlockGroupingCollector c = new BlockGroupingCollector(groupSort, topN, includeScores, groupEndDocs);
@@ -352,7 +352,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="maxCacheRAMMB">The maximum amount in MB the cache is allowed to hold</param>
         /// <param name="cacheScores">Whether to cache the scores</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheScores)
+        public virtual GroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheScores)
         {
             this.maxCacheRAMMB = maxCacheRAMMB;
             this.maxDocsToCache = null;
@@ -368,7 +368,7 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="maxDocsToCache">The maximum number of documents the cache is allowed to hold</param>
         /// <param name="cacheScores">Whether to cache the scores</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
+        public virtual GroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
         {
             this.maxDocsToCache = maxDocsToCache;
             this.maxCacheRAMMB = null;
@@ -380,7 +380,7 @@ namespace Lucene.Net.Search.Grouping
         /// Disables any enabled cache.
         /// </summary>
         /// <returns><c>this</c></returns>
-        public GroupingSearch DisableCaching()
+        public virtual GroupingSearch DisableCaching()
         {
             this.maxCacheRAMMB = null;
             this.maxDocsToCache = null;
@@ -393,7 +393,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="groupSort">The sort for the groups.</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetGroupSort(Sort groupSort)
+        public virtual GroupingSearch SetGroupSort(Sort groupSort)
         {
             this.groupSort = groupSort;
             return this;
@@ -405,7 +405,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="sortWithinGroup">The sort for documents inside a group</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
+        public virtual GroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
         {
             this.sortWithinGroup = sortWithinGroup;
             return this;
@@ -416,7 +416,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="groupDocsOffset">The offset for documents inside a</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetGroupDocsOffset(int groupDocsOffset)
+        public virtual GroupingSearch SetGroupDocsOffset(int groupDocsOffset)
         {
             this.groupDocsOffset = groupDocsOffset;
             return this;
@@ -427,7 +427,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="groupDocsLimit">The number of documents to return inside a group</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetGroupDocsLimit(int groupDocsLimit)
+        public virtual GroupingSearch SetGroupDocsLimit(int groupDocsLimit)
         {
             this.groupDocsLimit = groupDocsLimit;
             return this;
@@ -438,7 +438,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="fillSortFields">Whether to also fill the sort fields per returned group and groups docs</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetFillSortFields(bool fillSortFields)
+        public virtual GroupingSearch SetFillSortFields(bool fillSortFields)
         {
             this.fillSortFields = fillSortFields;
             return this;
@@ -449,7 +449,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="includeScores">Whether to include the scores per doc inside a group</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetIncludeScores(bool includeScores)
+        public virtual GroupingSearch SetIncludeScores(bool includeScores)
         {
             this.includeScores = includeScores;
             return this;
@@ -460,7 +460,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="includeMaxScore">Whether to include the score of the most relevant document per group</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetIncludeMaxScore(bool includeMaxScore)
+        public virtual GroupingSearch SetIncludeMaxScore(bool includeMaxScore)
         {
             this.includeMaxScore = includeMaxScore;
             return this;
@@ -476,7 +476,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="allGroups">to also compute all groups matching the query</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetAllGroups(bool allGroups)
+        public virtual GroupingSearch SetAllGroups(bool allGroups)
         {
             this.allGroups = allGroups;
             return this;
@@ -489,7 +489,7 @@ namespace Lucene.Net.Search.Grouping
         /// <typeparam name="T">The group value type. This can be a <see cref="BytesRef"/> or a <see cref="MutableValue"/> instance. 
         /// If grouping by doc block this the group value is always <c>null</c>.</typeparam>
         /// <returns>all matching groups are returned, or an empty collection</returns>
-        public ICollection<T> GetAllMatchingGroups<T>()
+        public virtual ICollection<T> GetAllMatchingGroups<T>()
         {
             return (ICollection<T>)matchingGroups;
         }
@@ -504,7 +504,7 @@ namespace Lucene.Net.Search.Grouping
         /// any type, since <see cref="GetAllMatchingGroups{T}"/>
         /// will throw an exception if the return type is incorrect.
         /// </remarks>
-        public ICollection GetAllMatchingGroups()
+        public virtual ICollection GetAllMatchingGroups()
         {
             return matchingGroups;
         }
@@ -517,7 +517,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="allGroupHeads">Whether to compute all group heads (most relevant document per group) matching the query</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetAllGroupHeads(bool allGroupHeads)
+        public virtual GroupingSearch SetAllGroupHeads(bool allGroupHeads)
         {
             this.allGroupHeads = allGroupHeads;
             return this;
@@ -527,7 +527,7 @@ namespace Lucene.Net.Search.Grouping
         /// Returns the matching group heads if <see cref="SetAllGroupHeads(bool)"/> was set to true or an empty bit set.
         /// </summary>
         /// <returns>The matching group heads if <see cref="SetAllGroupHeads(bool)"/> was set to true or an empty bit set</returns>
-        public Bits GetAllGroupHeads()
+        public virtual Bits GetAllGroupHeads()
         {
             return matchingGroupHeads;
         }
@@ -543,7 +543,7 @@ namespace Lucene.Net.Search.Grouping
         /// </summary>
         /// <param name="initialSize">The initial size of some internal used data structures</param>
         /// <returns><c>this</c></returns>
-        public GroupingSearch SetInitialSize(int initialSize)
+        public virtual GroupingSearch SetInitialSize(int initialSize)
         {
             this.initialSize = initialSize;
             return this;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96d38eff/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index a3ad0d3..b0116ae 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -338,7 +338,7 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-            public ICollection<SearchGroup<T>> Merge(IList<IEnumerable<ISearchGroup<T>>> shards, int offset, int topN)
+            public virtual ICollection<SearchGroup<T>> Merge(IList<IEnumerable<ISearchGroup<T>>> shards, int offset, int topN)
             {
 
                 int maxQueueSize = offset + topN;


[43/58] [abbrv] lucenenet git commit: Ported Grouping.DistinctValuesCollectorTest

Posted by ni...@apache.org.
Ported Grouping.DistinctValuesCollectorTest


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

Branch: refs/heads/grouping
Commit: 44c29eb8921d0c3d08493de6e2d3333b51aebe53
Parents: fa5f440
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 20:38:20 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:56 2016 +0700

----------------------------------------------------------------------
 .../AbstractDistinctValuesCollector.cs          |  36 +-
 .../Function/FunctionDistinctValuesCollector.cs |  18 +-
 .../Term/TermDistinctValuesCollector.cs         |  28 +-
 .../DistinctValuesCollectorTest.cs              | 327 +++++++++----------
 .../Lucene.Net.Tests.Grouping.csproj            |   1 +
 5 files changed, 207 insertions(+), 203 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/44c29eb8/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
index e9df8d8..0f51a24 100644
--- a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
@@ -13,13 +13,14 @@ namespace Lucene.Net.Search.Grouping
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="GC"></typeparam>
-    public abstract class AbstractDistinctValuesCollector<GC> : Collector where GC : IGroupCount /* AbstractDistinctValuesCollector<GC>.GroupCount */
+    public abstract class AbstractDistinctValuesCollector<GC> : Collector, IAbstractDistinctValuesCollector<GC>
+        where GC : IGroupCount /* AbstractDistinctValuesCollector<GC>.GroupCount */
     {
         /// <summary>
         /// Returns all unique values for each top N group.
         /// </summary>
         /// <returns>all unique values for each top N group</returns>
-        public abstract List<GC> GetGroups();
+        public abstract IEnumerable<GC> Groups { get; }
 
         public override bool AcceptsDocsOutOfOrder()
         {
@@ -66,16 +67,16 @@ namespace Lucene.Net.Search.Grouping
     /// <see cref="AbstractDistinctValuesCollector{GC}"/> and renamed
     /// from GroupCount to AbstractGroupCount
     /// </remarks>
-    public abstract class AbstractGroupCount<TGroupValue> : IGroupCount
+    public abstract class AbstractGroupCount<TGroupValue> : IGroupCount<TGroupValue>
         //where TGroupValue : IComparable
     {
-        public readonly TGroupValue groupValue;
-        public readonly ISet<TGroupValue> uniqueValues;
+        public TGroupValue GroupValue { get; protected set; }
+        public IEnumerable<TGroupValue> UniqueValues { get; protected set; }
 
         public AbstractGroupCount(TGroupValue groupValue)
         {
-            this.groupValue = groupValue;
-            this.uniqueValues = new HashSet<TGroupValue>();
+            this.GroupValue = groupValue;
+            this.UniqueValues = new HashSet<TGroupValue>();
         }
     }
 
@@ -86,4 +87,25 @@ namespace Lucene.Net.Search.Grouping
     public interface IGroupCount
     {
     }
+
+
+    /// <summary>
+    /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public interface IGroupCount<out TGroupValue> : IGroupCount
+    {
+        TGroupValue GroupValue { get; }
+        IEnumerable<TGroupValue> UniqueValues { get; }
+    }
+
+
+    /// <summary>
+    /// LUCENENET specific interface used to apply covariance to GC
+    /// </summary>
+    /// <typeparam name="GC"></typeparam>
+    public interface IAbstractDistinctValuesCollector<out GC>
+    {
+        IEnumerable<GC> Groups { get; }
+    }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/44c29eb8/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
index 3d5dc0a..2d5b9ee 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
@@ -1,13 +1,9 @@
-\ufeffusing Lucene.Net.Queries.Function;
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
 using Lucene.Net.Support;
 using Lucene.Net.Util.Mutable;
-using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Lucene.Net.Index;
 
 namespace Lucene.Net.Search.Grouping.Function
 {
@@ -28,21 +24,21 @@ namespace Lucene.Net.Search.Grouping.Function
         private MutableValue groupMval;
         private MutableValue countMval;
 
-        public FunctionDistinctValuesCollector(IDictionary /*Map<?, ?>*/ vsContext, ValueSource groupSource, ValueSource countSource, ICollection<SearchGroup<MutableValue>> groups)
+        public FunctionDistinctValuesCollector(IDictionary /*Map<?, ?>*/ vsContext, ValueSource groupSource, ValueSource countSource, IEnumerable<ISearchGroup<MutableValue>> groups)
         {
             this.vsContext = vsContext;
             this.groupSource = groupSource;
             this.countSource = countSource;
-            groupMap = new LurchTable<MutableValue, GroupCount>(1 << 4);
+            groupMap = new LinkedHashMap<MutableValue, GroupCount>();
             foreach (SearchGroup<MutableValue> group in groups)
             {
                 groupMap[group.GroupValue] = new GroupCount(group.GroupValue);
             }
         }
 
-        public override List<GroupCount> GetGroups()
+        public override IEnumerable<GroupCount> Groups
         {
-            return new List<GroupCount>(groupMap.Values);
+            get { return new List<GroupCount>(groupMap.Values); }
         }
 
         public override void Collect(int doc)
@@ -52,7 +48,7 @@ namespace Lucene.Net.Search.Grouping.Function
             if (groupMap.TryGetValue(groupMval, out groupCount))
             {
                 countFiller.FillValue(doc);
-                groupCount.uniqueValues.Add(countMval.Duplicate());
+                ((ISet<MutableValue>)groupCount.UniqueValues).Add(countMval.Duplicate());
             }
         }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/44c29eb8/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
index 502b0ea..ac4d4e9 100644
--- a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
@@ -1,12 +1,9 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Support;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
@@ -34,16 +31,17 @@ namespace Lucene.Net.Search.Grouping.Terms
          * @param countField The field to count distinct values for
          * @param groups The top N groups, collected during the first phase search
          */
-        public TermDistinctValuesCollector(string groupField, string countField, ICollection<SearchGroup<BytesRef>> groups)
+        public TermDistinctValuesCollector(string groupField, string countField, IEnumerable<ISearchGroup<BytesRef>> groups)
         {
             this.groupField = groupField;
             this.countField = countField;
-            this.groups = new List<GroupCount>(groups.Count);
-            foreach (SearchGroup<BytesRef> group in groups)
+            int groupCount = groups.Count();
+            this.groups = new List<GroupCount>(groupCount);
+            foreach (ISearchGroup<BytesRef> group in groups)
             {
                 this.groups.Add(new GroupCount(group.GroupValue));
             }
-            ordSet = new SentinelIntSet(groups.Count, -2);
+            ordSet = new SentinelIntSet(groupCount, -2);
             groupCounts = new GroupCount[ordSet.Keys.Length];
         }
 
@@ -61,13 +59,13 @@ namespace Lucene.Net.Search.Grouping.Terms
             {
                 if (countOrd == -1)
                 {
-                    gc.uniqueValues.Add(null);
+                    ((ISet<BytesRef>)gc.UniqueValues).Add(null);
                 }
                 else
                 {
                     BytesRef br = new BytesRef();
                     countFieldTermIndex.LookupOrd(countOrd, br);
-                    gc.uniqueValues.Add(br);
+                    ((ISet<BytesRef>)gc.UniqueValues).Add(br);
                 }
 
                 gc.ords = Arrays.CopyOf(gc.ords, gc.ords.Length + 1);
@@ -92,9 +90,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             return Array.BinarySearch(ords, ord) < 0;
         }
 
-        public override List<GroupCount> GetGroups()
+        public override IEnumerable<GroupCount> Groups
         {
-            return groups;
+            get { return groups; }
         }
 
         public override AtomicReaderContext NextReader
@@ -106,17 +104,17 @@ namespace Lucene.Net.Search.Grouping.Terms
                 ordSet.Clear();
                 foreach (GroupCount group in groups)
                 {
-                    int groupOrd = group.groupValue == null ? -1 : groupFieldTermIndex.LookupTerm(group.groupValue);
-                    if (group.groupValue != null && groupOrd < 0)
+                    int groupOrd = group.GroupValue == null ? -1 : groupFieldTermIndex.LookupTerm(group.GroupValue);
+                    if (group.GroupValue != null && groupOrd < 0)
                     {
                         continue;
                     }
 
                     groupCounts[ordSet.Put(groupOrd)] = group;
-                    group.ords = new int[group.uniqueValues.Count];
+                    group.ords = new int[group.UniqueValues.Count()];
                     Arrays.Fill(group.ords, -2);
                     int i = 0;
-                    foreach (BytesRef value2 in group.uniqueValues)
+                    foreach (BytesRef value2 in group.UniqueValues)
                     {
                         int countOrd = value2 == null ? -1 : countFieldTermIndex.LookupTerm(value2);
                         if (value2 == null || countOrd >= 0)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/44c29eb8/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
index 854050b..58fae2c 100644
--- a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
@@ -1,10 +1,9 @@
 \ufeffusing Lucene.Net.Analysis;
 using Lucene.Net.Documents;
-using Lucene.Net.Search.Grouping.Function;
-using Lucene.Net.Search.Grouping.Term;
 using Lucene.Net.Index;
 using Lucene.Net.Queries.Function.ValueSources;
-using Lucene.Net.Search;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Search.Grouping.Terms;
 using Lucene.Net.Store;
 using Lucene.Net.Support;
 using Lucene.Net.Util;
@@ -15,10 +14,6 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Lucene.Net.Search.Grouping;
-using Lucene.Net.Search.Grouping.Terms;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -31,7 +26,7 @@ namespace Lucene.Net.Search.Grouping
         private readonly string countField = "publisher";
         private readonly string dvCountField = "publisher_dv";
 
-        internal class ComparerAnonymousHelper1 : IComparer<AbstractGroupCount<IComparable<object>>>
+        internal class ComparerAnonymousHelper1 : IComparer<IGroupCount<IComparable>>
         {
             private readonly DistinctValuesCollectorTest outerInstance;
 
@@ -40,29 +35,29 @@ namespace Lucene.Net.Search.Grouping
                 this.outerInstance = outerInstance;
             }
 
-            public int Compare(AbstractGroupCount<IComparable<object>> groupCount1, AbstractGroupCount<IComparable<object>> groupCount2)
+            public int Compare(IGroupCount<IComparable> groupCount1, IGroupCount<IComparable> groupCount2)
             {
-                if (groupCount1.groupValue == null)
+                if (groupCount1.GroupValue == null)
                 {
-                    if (groupCount2.groupValue == null)
+                    if (groupCount2.GroupValue == null)
                     {
                         return 0;
                     }
                     return -1;
                 }
-                else if (groupCount2.groupValue == null)
+                else if (groupCount2.GroupValue == null)
                 {
                     return 1;
                 }
                 else
                 {
-                    return groupCount1.groupValue.CompareTo(groupCount2.groupValue);
+                    return groupCount1.GroupValue.CompareTo(groupCount2.GroupValue);
                 }
             }
         }
 
         [Test]
-        public void TestSimple()
+        public virtual void TestSimple()
         {
             Random random = Random();
             FieldInfo.DocValuesType_e[] dvTypes = new FieldInfo.DocValuesType_e[]{
@@ -80,24 +75,24 @@ namespace Lucene.Net.Search.Grouping
             FieldInfo.DocValuesType_e? dvType = canUseDV ? dvTypes[random.nextInt(dvTypes.Length)] : (FieldInfo.DocValuesType_e?)null;
 
             Document doc = new Document();
-            addField(doc, groupField, "1", dvType);
-            addField(doc, countField, "1", dvType);
+            AddField(doc, groupField, "1", dvType);
+            AddField(doc, countField, "1", dvType);
             doc.Add(new TextField("content", "random text", Field.Store.NO));
             doc.Add(new StringField("id", "1", Field.Store.NO));
             w.AddDocument(doc);
 
             // 1
             doc = new Document();
-            addField(doc, groupField, "1", dvType);
-            addField(doc, countField, "1", dvType);
+            AddField(doc, groupField, "1", dvType);
+            AddField(doc, countField, "1", dvType);
             doc.Add(new TextField("content", "some more random text blob", Field.Store.NO));
             doc.Add(new StringField("id", "2", Field.Store.NO));
             w.AddDocument(doc);
 
             // 2
             doc = new Document();
-            addField(doc, groupField, "1", dvType);
-            addField(doc, countField, "2", dvType);
+            AddField(doc, groupField, "1", dvType);
+            AddField(doc, countField, "2", dvType);
             doc.Add(new TextField("content", "some more random textual data", Field.Store.NO));
             doc.Add(new StringField("id", "3", Field.Store.NO));
             w.AddDocument(doc);
@@ -105,23 +100,23 @@ namespace Lucene.Net.Search.Grouping
 
             // 3
             doc = new Document();
-            addField(doc, groupField, "2", dvType);
+            AddField(doc, groupField, "2", dvType);
             doc.Add(new TextField("content", "some random text", Field.Store.NO));
             doc.Add(new StringField("id", "4", Field.Store.NO));
             w.AddDocument(doc);
 
             // 4
             doc = new Document();
-            addField(doc, groupField, "3", dvType);
-            addField(doc, countField, "1", dvType);
+            AddField(doc, groupField, "3", dvType);
+            AddField(doc, countField, "1", dvType);
             doc.Add(new TextField("content", "some more random text", Field.Store.NO));
             doc.Add(new StringField("id", "5", Field.Store.NO));
             w.AddDocument(doc);
 
             // 5
             doc = new Document();
-            addField(doc, groupField, "3", dvType);
-            addField(doc, countField, "1", dvType);
+            AddField(doc, groupField, "3", dvType);
+            AddField(doc, countField, "1", dvType);
             doc.Add(new TextField("content", "random blob", Field.Store.NO));
             doc.Add(new StringField("id", "6", Field.Store.NO));
             w.AddDocument(doc);
@@ -129,7 +124,7 @@ namespace Lucene.Net.Search.Grouping
             // 6 -- no author field
             doc = new Document();
             doc.Add(new TextField("content", "random word stuck in alot of other text", Field.Store.YES));
-            addField(doc, countField, "1", dvType);
+            AddField(doc, countField, "1", dvType);
             doc.Add(new StringField("id", "6", Field.Store.NO));
             w.AddDocument(doc);
 
@@ -138,147 +133,140 @@ namespace Lucene.Net.Search.Grouping
 
             var cmp = new ComparerAnonymousHelper1(this);
 
-            //    Comparator<AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>> cmp = new Comparator<AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>>() {
-
-            //      @Override
-            //      public int compare(AbstractDistinctValuesCollector.GroupCount<Comparable<Object>> groupCount1, AbstractDistinctValuesCollector.GroupCount<Comparable<Object>> groupCount2)
-            //    {
-            //        if (groupCount1.groupValue == null)
-            //        {
-            //            if (groupCount2.groupValue == null)
-            //            {
-            //                return 0;
-            //            }
-            //            return -1;
-            //        }
-            //        else if (groupCount2.groupValue == null)
-            //        {
-            //            return 1;
-            //        }
-            //        else
-            //        {
-            //            return groupCount1.groupValue.compareTo(groupCount2.groupValue);
-            //        }
-            //    }
-
-            //};
-
             // === Search for content:random
-            AbstractFirstPassGroupingCollector<IComparable<object>> firstCollector = createRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
-            indexSearcher.Search(new TermQuery(new Term("content", "random")), firstCollector);
-            Collector distinctValuesCollector
-                = createDistinctCountCollector(firstCollector, groupField, countField, dvType.GetValueOrDefault());
-            indexSearcher.Search(new TermQuery(new Term("content", "random")), distinctValuesCollector);
-
-            var gcs = distinctValuesCollector.GetGroups();
-            //Collections.sort(gcs, cmp);
+            IAbstractFirstPassGroupingCollector<IComparable> firstCollector = CreateRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), firstCollector as Collector);
+            IAbstractDistinctValuesCollector<IGroupCount<IComparable>> distinctValuesCollector
+                = CreateDistinctCountCollector(firstCollector, groupField, countField, dvType.GetValueOrDefault());
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), distinctValuesCollector as Collector);
+
+            //var gcs = distinctValuesCollector.Groups as List<IGroupCount<IComparable>>;
+            // LUCENENET TODO: Try to work out how to do this without an O(n) operation
+            var gcs = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
             gcs.Sort(cmp);
             assertEquals(4, gcs.Count);
 
-            compareNull(gcs[0].groupValue);
-            List<IComparable> countValues = new List<IComparable>(gcs[0].uniqueValues);
+            CompareNull(gcs[0].GroupValue);
+            List<IComparable> countValues = new List<IComparable>(gcs[0].UniqueValues);
             assertEquals(1, countValues.size());
-            compare("1", countValues[0]);
+            Compare("1", countValues[0]);
 
-            compare("1", gcs[1].groupValue);
-            countValues = new List<IComparable>(gcs[1].uniqueValues);
-            //Collections.sort(countValues, nullComparator);
+            Compare("1", gcs[1].GroupValue);
+            countValues = new List<IComparable>(gcs[1].UniqueValues);
             countValues.Sort(nullComparator);
             assertEquals(2, countValues.size());
-            compare("1", countValues[0]);
-            compare("2", countValues[1]);
+            Compare("1", countValues[0]);
+            Compare("2", countValues[1]);
 
-            compare("2", gcs[2].groupValue);
-            countValues = new List<IComparable>(gcs[2].uniqueValues);
+            Compare("2", gcs[2].GroupValue);
+            countValues = new List<IComparable>(gcs[2].UniqueValues);
             assertEquals(1, countValues.size());
-            compareNull(countValues[0]);
+            CompareNull(countValues[0]);
 
-            compare("3", gcs[3].groupValue);
-            countValues = new List<IComparable>(gcs[3].uniqueValues);
+            Compare("3", gcs[3].GroupValue);
+            countValues = new List<IComparable>(gcs[3].UniqueValues);
             assertEquals(1, countValues.size());
-            compare("1", countValues[0]);
+            Compare("1", countValues[0]);
 
             // === Search for content:some
-            firstCollector = createRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
-            indexSearcher.Search(new TermQuery(new Term("content", "some")), firstCollector);
-            distinctValuesCollector = createDistinctCountCollector(firstCollector, groupField, countField, dvType);
-            indexSearcher.Search(new TermQuery(new Term("content", "some")), distinctValuesCollector);
-
-            gcs = distinctValuesCollector.getGroups();
-            //Collections.sort(gcs, cmp);
+            firstCollector = CreateRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), firstCollector as Collector);
+            distinctValuesCollector = CreateDistinctCountCollector(firstCollector, groupField, countField, dvType);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), distinctValuesCollector as Collector);
+
+            // LUCENENET TODO: Try to work out how to do this without an O(n) operation
+            //gcs = distinctValuesCollector.Groups as List<IGroupCount<IComparable>>;
+            gcs = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
             gcs.Sort(cmp);
             assertEquals(3, gcs.Count);
 
-            compare("1", gcs.get(0).groupValue);
-            countValues = new List<IComparable>(gcs[0].uniqueValues);
+            Compare("1", gcs[0].GroupValue);
+            countValues = new List<IComparable>(gcs[0].UniqueValues);
             assertEquals(2, countValues.size());
-            //Collections.sort(countValues, nullComparator);
             countValues.Sort(nullComparator);
-            compare("1", countValues[0]);
-            compare("2", countValues[1]);
+            Compare("1", countValues[0]);
+            Compare("2", countValues[1]);
 
-            compare("2", gcs[1].groupValue);
-            countValues = new List<IComparable>(gcs[1].uniqueValues);
+            Compare("2", gcs[1].GroupValue);
+            countValues = new List<IComparable>(gcs[1].UniqueValues);
             assertEquals(1, countValues.size());
-            compareNull(countValues[0]);
+            CompareNull(countValues[0]);
 
-            compare("3", gcs.get(2).groupValue);
-            countValues = new List<IComparable>(gcs.get(2).uniqueValues);
+            Compare("3", gcs[2].GroupValue);
+            countValues = new List<IComparable>(gcs[2].UniqueValues);
             assertEquals(1, countValues.size());
-            compare("1", countValues[0]);
+            Compare("1", countValues[0]);
 
             // === Search for content:blob
-            firstCollector = createRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
-            indexSearcher.search(new TermQuery(new Term("content", "blob")), firstCollector);
-            distinctValuesCollector = createDistinctCountCollector(firstCollector, groupField, countField, dvType);
-            indexSearcher.search(new TermQuery(new Term("content", "blob")), distinctValuesCollector);
-
-            gcs = distinctValuesCollector.getGroups();
-            //Collections.sort(gcs, cmp);
+            firstCollector = CreateRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "blob")), firstCollector as Collector);
+            distinctValuesCollector = CreateDistinctCountCollector(firstCollector, groupField, countField, dvType);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "blob")), distinctValuesCollector as Collector);
+
+            // LUCENENET TODO: Try to work out how to do this without an O(n) operation
+            //gcs = distinctValuesCollector.Groups as List<IGroupCount<IComparable>>;
+            gcs = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
             gcs.Sort(cmp);
             assertEquals(2, gcs.Count);
 
-            compare("1", gcs[0].groupValue);
-            countValues = new List<IComparable>(gcs[0].uniqueValues);
+            Compare("1", gcs[0].GroupValue);
+            countValues = new List<IComparable>(gcs[0].UniqueValues);
             // B/c the only one document matched with blob inside the author 1 group
             assertEquals(1, countValues.Count);
-            compare("1", countValues[0]);
+            Compare("1", countValues[0]);
 
-            compare("3", gcs[1].groupValue);
-            countValues = new List<IComparable>(gcs[1].uniqueValues);
+            Compare("3", gcs[1].GroupValue);
+            countValues = new List<IComparable>(gcs[1].UniqueValues);
             assertEquals(1, countValues.Count);
-            compare("1", countValues[0]);
+            Compare("1", countValues[0]);
 
             indexSearcher.IndexReader.Dispose();
             dir.Dispose();
         }
 
         [Test]
-        public void testRandom()
+        public virtual void TestRandom()
         {
             Random random = Random();
             int numberOfRuns = TestUtil.NextInt(random, 3, 6);
             for (int indexIter = 0; indexIter < numberOfRuns; indexIter++)
             {
-                IndexContext context = createIndexContext();
+                IndexContext context = CreateIndexContext();
                 for (int searchIter = 0; searchIter < 100; searchIter++)
                 {
                     IndexSearcher searcher = NewSearcher(context.indexReader);
                     bool useDv = context.dvType != null && random.nextBoolean();
-                    FieldInfo.DocValuesType_e? dvType = useDv ? context.dvType : (FieldInfo.DocValuesType_e?)null;
+                    FieldInfo.DocValuesType_e? dvType = useDv ? context.dvType : null;
                     string term = context.contentStrings[random.nextInt(context.contentStrings.Length)];
                     Sort groupSort = new Sort(new SortField("id", SortField.Type_e.STRING));
                     int topN = 1 + random.nextInt(10);
 
-                    List<AbstractGroupCount<IComparable>> expectedResult = createExpectedResult(context, term, groupSort, topN);
+                    List<IGroupCount<IComparable>> expectedResult = CreateExpectedResult(context, term, groupSort, topN);
 
-                    AbstractFirstPassGroupingCollector < Comparable <?>> firstCollector = createRandomFirstPassCollector(dvType, groupSort, groupField, topN);
-                    searcher.Search(new TermQuery(new Term("content", term)), firstCollector);
-                    AbstractDistinctValuesCollector <? extends AbstractDistinctValuesCollector.GroupCount < Comparable <?>>> distinctValuesCollector
-                        = createDistinctCountCollector(firstCollector, groupField, countField, dvType);
-                    searcher.Search(new TermQuery(new Term("content", term)), distinctValuesCollector);
+                    IAbstractFirstPassGroupingCollector<IComparable> firstCollector = CreateRandomFirstPassCollector(dvType, groupSort, groupField, topN);
+                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                    searcher.Search(new TermQuery(new Term("content", term)), firstCollector as Collector);
+                    IAbstractDistinctValuesCollector<IGroupCount<IComparable>> distinctValuesCollector
+                        = CreateDistinctCountCollector(firstCollector, groupField, countField, dvType);
+                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                    searcher.Search(new TermQuery(new Term("content", term)), distinctValuesCollector as Collector);
 
-                    List<AbstractGroupCount<IComparable>> actualResult = (List<AbstractGroupCount<IComparable>>)distinctValuesCollector.Groups;
+                    // LUCENENET TODO: Try to work out how to do this without an O(n) operation
+                    List<IGroupCount<IComparable>> actualResult = new List<IGroupCount<IComparable>>(distinctValuesCollector.Groups);
 
                     if (VERBOSE)
                     {
@@ -288,27 +276,28 @@ namespace Lucene.Net.Search.Grouping
                         Console.WriteLine("2nd pass collector class name=" + distinctValuesCollector.GetType().Name);
                         Console.WriteLine("Search term=" + term);
                         Console.WriteLine("DVType=" + dvType);
-                        Console.WriteLine("1st pass groups=" + firstCollector.GetTopGroups(0, false));
+                        Console.WriteLine("1st pass groups=" + firstCollector.GetTopGroups(0, false).toString());
                         Console.WriteLine("Expected:");
-                        printGroups(expectedResult);
+                        PrintGroups(expectedResult);
                         Console.WriteLine("Actual:");
-                        printGroups(actualResult);
+                        PrintGroups(actualResult);
+                        Console.Out.Flush();
                     }
 
                     assertEquals(expectedResult.Count, actualResult.Count);
                     for (int i = 0; i < expectedResult.size(); i++)
                     {
-                        AbstractDistinctValuesCollector.GroupCount < Comparable <?>> expected = expectedResult.get(i);
-                        AbstractDistinctValuesCollector.GroupCount < Comparable <?>> actual = actualResult.get(i);
-                        assertValues(expected.groupValue, actual.groupValue);
-                        assertEquals(expected.uniqueValues.size(), actual.uniqueValues.size());
-                        List < Comparable <?>> expectedUniqueValues = new ArrayList<>(expected.uniqueValues);
-                        Collections.sort(expectedUniqueValues, nullComparator);
-                        List < Comparable <?>> actualUniqueValues = new ArrayList<>(actual.uniqueValues);
-                        Collections.sort(actualUniqueValues, nullComparator);
+                        IGroupCount<IComparable> expected = expectedResult[i];
+                        IGroupCount<IComparable> actual = actualResult[i];
+                        AssertValues(expected.GroupValue, actual.GroupValue);
+                        assertEquals(expected.UniqueValues.Count(), actual.UniqueValues.Count());
+                        List<IComparable> expectedUniqueValues = new List<IComparable>(expected.UniqueValues);
+                        expectedUniqueValues.Sort(nullComparator);
+                        List<IComparable> actualUniqueValues = new List<IComparable>(actual.UniqueValues);
+                        actualUniqueValues.Sort(nullComparator);
                         for (int j = 0; j < expectedUniqueValues.size(); j++)
                         {
-                            assertValues(expectedUniqueValues.get(j), actualUniqueValues.get(j));
+                            AssertValues(expectedUniqueValues[j], actualUniqueValues[j]);
                         }
                     }
                 }
@@ -317,12 +306,12 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void printGroups(List<AbstractDistinctValuesCollector.GroupCount<IComparable>> results)
+        private void PrintGroups(List<IGroupCount<IComparable>> results)
         {
             for (int i = 0; i < results.size(); i++)
             {
                 var group = results[i];
-                object gv = group.groupValue;
+                object gv = group.GroupValue;
                 if (gv is BytesRef)
                 {
                     Console.WriteLine(i + ": groupValue=" + ((BytesRef)gv).Utf8ToString());
@@ -331,7 +320,7 @@ namespace Lucene.Net.Search.Grouping
                 {
                     Console.WriteLine(i + ": groupValue=" + gv);
                 }
-                foreach (object o in group.uniqueValues)
+                foreach (object o in group.UniqueValues)
                 {
                     if (o is BytesRef)
                     {
@@ -345,19 +334,19 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void assertValues(object expected, object actual)
+        private void AssertValues(object expected, object actual)
         {
             if (expected == null)
             {
-                compareNull(actual);
+                CompareNull(actual);
             }
             else
             {
-                compare(((BytesRef)expected).Utf8ToString(), actual);
+                Compare(((BytesRef)expected).Utf8ToString(), actual);
             }
         }
 
-        private void compare(string expected, object groupValue)
+        private void Compare(string expected, object groupValue)
         {
             if (typeof(BytesRef).IsAssignableFrom(groupValue.GetType()))
             {
@@ -383,7 +372,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void compareNull(object groupValue)
+        private void CompareNull(object groupValue)
         {
             if (groupValue == null)
             {
@@ -413,7 +402,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void addField(Document doc, string field, string value, FieldInfo.DocValuesType_e? type)
+        private void AddField(Document doc, string field, string value, FieldInfo.DocValuesType_e? type)
         {
             doc.Add(new StringField(field, value, Field.Store.YES));
             if (type == null)
@@ -438,65 +427,66 @@ namespace Lucene.Net.Search.Grouping
             doc.Add(valuesField);
         }
 
-        private AbstractDistinctValuesCollector<AbstractGroupCount<T>> createDistinctCountCollector<T>(AbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
+        private IAbstractDistinctValuesCollector<IGroupCount<T>> CreateDistinctCountCollector<T>(IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
                                                                             string groupField,
                                                                             string countField,
-                                                                            FieldInfo.DocValuesType_e dvType)
-                  where T : IComparable
+                                                                            FieldInfo.DocValuesType_e? dvType)
         {
             Random random = Random();
-            ICollection<SearchGroup<T>> searchGroups = firstPassGroupingCollector.GetTopGroups(0, false);
+            IEnumerable<ISearchGroup<T>> searchGroups = firstPassGroupingCollector.GetTopGroups(0, false);
             if (typeof(FunctionFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
             {
-                return (AbstractDistinctValuesCollector)new FunctionDistinctValuesCollector(new Hashtable(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), searchGroups as ICollection<SearchGroup<MutableValue>>);
+                return (IAbstractDistinctValuesCollector<IGroupCount<T>>)new FunctionDistinctValuesCollector(new Hashtable(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), searchGroups as IEnumerable<ISearchGroup<MutableValue>>);
             }
             else
             {
-                return (AbstractDistinctValuesCollector)new TermDistinctValuesCollector(groupField, countField, searchGroups as ICollection<SearchGroup<BytesRef>>);
+                return (IAbstractDistinctValuesCollector<IGroupCount<T>>)new TermDistinctValuesCollector(groupField, countField, searchGroups as IEnumerable<ISearchGroup<BytesRef>>);
             }
         }
 
-        private AbstractFirstPassGroupingCollector<T> createRandomFirstPassCollector<T>(FieldInfo.DocValuesType_e dvType, Sort groupSort, string groupField, int topNGroups)
+        private IAbstractFirstPassGroupingCollector<IComparable> CreateRandomFirstPassCollector(FieldInfo.DocValuesType_e? dvType, Sort groupSort, string groupField, int topNGroups)
         {
             Random random = Random();
             if (dvType != null)
             {
                 if (random.nextBoolean())
                 {
-                    return (AbstractFirstPassGroupingCollector<T>)new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new Hashtable(), groupSort, topNGroups);
+                    return new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new Hashtable(), groupSort, topNGroups)
+                        as IAbstractFirstPassGroupingCollector<IComparable>;
                 }
                 else
                 {
-                    return (AbstractFirstPassGroupingCollector<T>)new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
+                    return new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups)
+                        as IAbstractFirstPassGroupingCollector<IComparable>;
                 }
             }
             else
             {
                 if (random.nextBoolean())
                 {
-                    return (AbstractFirstPassGroupingCollector<T>)new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new Hashtable(), groupSort, topNGroups);
+                    return new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new Hashtable(), groupSort, topNGroups)
+                        as IAbstractFirstPassGroupingCollector<IComparable>;
                 }
                 else
                 {
-                    return (AbstractFirstPassGroupingCollector<T>)new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
+                    return new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups)
+                        as IAbstractFirstPassGroupingCollector<IComparable>;
                 }
             }
         }
 
         internal class GroupCount : AbstractGroupCount<BytesRef>
         {
-            internal GroupCount(BytesRef groupValue, ICollection<BytesRef> uniqueValues)
+            internal GroupCount(BytesRef groupValue, IEnumerable<BytesRef> uniqueValues)
                 : base(groupValue)
             {
-                this.uniqueValues.UnionWith(uniqueValues);
+                ((ISet<BytesRef>)this.UniqueValues).UnionWith(uniqueValues);
             }
         }
 
-        private List<AbstractGroupCount<IComparable>> createExpectedResult(IndexContext context, string term, Sort groupSort, int topN)
+        private List<IGroupCount<IComparable>> CreateExpectedResult(IndexContext context, string term, Sort groupSort, int topN)
         {
-
-
-            List<AbstractGroupCount<IComparable>> result = new List<AbstractGroupCount<IComparable>>();
+            List<IGroupCount<IComparable>> result = new List<IGroupCount<IComparable>>();
             IDictionary<string, ISet<string>> groupCounts = context.searchTermToGroupCounts[term];
             int i = 0;
             foreach (string group in groupCounts.Keys)
@@ -510,18 +500,19 @@ namespace Lucene.Net.Search.Grouping
                 {
                     uniqueValues.Add(val != null ? new BytesRef(val) : null);
                 }
-                result.Add(new GroupCount(group != null ? new BytesRef(group) : (BytesRef)null, uniqueValues));
+                var gc = new GroupCount(group != null ? new BytesRef(group) : (BytesRef)null, uniqueValues);
+                result.Add(gc);
             }
             return result;
         }
 
-        private IndexContext createIndexContext()
+        private IndexContext CreateIndexContext()
         {
             Random random = Random();
-            FieldInfo.DocValuesType_e[] dvTypes = new FieldInfo.DocValuesType_e[]{
-        FieldInfo.DocValuesType_e.BINARY,
-        FieldInfo.DocValuesType_e.SORTED
-    };
+                FieldInfo.DocValuesType_e[] dvTypes = new FieldInfo.DocValuesType_e[]{
+                FieldInfo.DocValuesType_e.BINARY,
+                FieldInfo.DocValuesType_e.SORTED
+            };
 
             Directory dir = NewDirectory();
             RandomIndexWriter w = new RandomIndexWriter(
@@ -547,28 +538,24 @@ namespace Lucene.Net.Search.Grouping
             }
 
             List<string> contentStrings = new List<string>();
-            IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts = new Dictionary<string, IDictionary<string, ISet<string>>>();
+            IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts = new HashMap<string, IDictionary<string, ISet<string>>>();
             for (int i = 1; i <= numDocs; i++)
             {
                 string groupValue = random.nextInt(23) == 14 ? null : groupValues[random.nextInt(groupValues.Length)];
                 string countValue = random.nextInt(21) == 13 ? null : countValues[random.nextInt(countValues.Length)];
                 string content = "random" + random.nextInt(numDocs / 20);
-                //IDictionary<string, ISet<string>> groupToCounts = searchTermToGroupCounts[content];
-                //      if (groupToCounts == null)
                 IDictionary<string, ISet<string>> groupToCounts;
                 if (!searchTermToGroupCounts.TryGetValue(content, out groupToCounts))
                 {
                     // Groups sort always DOCID asc...
-                    searchTermToGroupCounts[content] = groupToCounts = new LurchTable<string, ISet<string>>(16);
+                    searchTermToGroupCounts.Add(content, groupToCounts = new LinkedHashMap<string, ISet<string>>());
                     contentStrings.Add(content);
                 }
 
-                //ISet<string> countsVals = groupToCounts.get(groupValue);
-                //if (countsVals == null)
                 ISet<string> countsVals;
                 if (!groupToCounts.TryGetValue(groupValue, out countsVals))
                 {
-                    groupToCounts[groupValue] = countsVals = new HashSet<string>();
+                    groupToCounts.Add(groupValue, countsVals = new HashSet<string>());
                 }
                 countsVals.Add(countValue);
 
@@ -576,11 +563,11 @@ namespace Lucene.Net.Search.Grouping
                 doc.Add(new StringField("id", string.Format(CultureInfo.InvariantCulture, "{0:D9}", i), Field.Store.YES));
                 if (groupValue != null)
                 {
-                    addField(doc, groupField, groupValue, dvType);
+                    AddField(doc, groupField, groupValue, dvType);
                 }
                 if (countValue != null)
                 {
-                    addField(doc, countField, countValue, dvType);
+                    AddField(doc, countField, countValue, dvType);
                 }
                 doc.Add(new TextField("content", content, Field.Store.YES));
                 w.AddDocument(doc);
@@ -597,7 +584,7 @@ namespace Lucene.Net.Search.Grouping
             }
 
             w.Dispose();
-            return new IndexContext(dir, reader, dvType.GetValueOrDefault(), searchTermToGroupCounts, contentStrings.ToArray(/*new String[contentStrings.size()]*/));
+            return new IndexContext(dir, reader, dvType, searchTermToGroupCounts, contentStrings.ToArray(/*new String[contentStrings.size()]*/));
         }
 
         internal class IndexContext
@@ -605,11 +592,11 @@ namespace Lucene.Net.Search.Grouping
 
             internal readonly Directory directory;
             internal readonly DirectoryReader indexReader;
-            internal readonly FieldInfo.DocValuesType_e dvType;
+            internal readonly FieldInfo.DocValuesType_e? dvType;
             internal readonly IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts;
             internal readonly string[] contentStrings;
 
-            internal IndexContext(Directory directory, DirectoryReader indexReader, FieldInfo.DocValuesType_e dvType,
+            internal IndexContext(Directory directory, DirectoryReader indexReader, FieldInfo.DocValuesType_e? dvType,
                          IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts, string[] contentStrings)
             {
                 this.directory = directory;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/44c29eb8/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
index cc96210..f5906f1 100644
--- a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
+++ b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
@@ -47,6 +47,7 @@
     <Compile Include="AbstractGroupingTestCase.cs" />
     <Compile Include="AllGroupHeadsCollectorTest.cs" />
     <Compile Include="AllGroupsCollectorTest.cs" />
+    <Compile Include="DistinctValuesCollectorTest.cs" />
     <Compile Include="GroupFacetCollectorTest.cs" />
     <Compile Include="GroupingSearchTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />


[38/58] [abbrv] lucenenet git commit: Fixed compile issues with Join.TestBlockJoin after applying IGroupDocs in place of GroupDocs on TopGroups.

Posted by ni...@apache.org.
Fixed compile issues with Join.TestBlockJoin after applying IGroupDocs in place of GroupDocs on TopGroups.


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

Branch: refs/heads/grouping
Commit: 7c2c58138999bb31375bccba3e0d8474402e2e83
Parents: 28cd391
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 20:24:15 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:55 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Tests.Join/TestBlockJoin.cs | 26 ++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7c2c5813/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Join/TestBlockJoin.cs b/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
index c140c75..c87a6b7 100644
--- a/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
+++ b/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
@@ -4,7 +4,7 @@ using System.Linq;
 using System.Text;
 using Lucene.Net.Analysis;
 using Lucene.Net.Documents;
-using Lucene.Net.Grouping;
+using Lucene.Net.Search.Grouping;
 using Lucene.Net.Index;
 using Lucene.Net.Join;
 using Lucene.Net.Randomized;
@@ -116,7 +116,7 @@ namespace Lucene.Net.Tests.Join
             assertFalse(float.IsNaN(results.MaxScore));
             assertEquals(1, results.TotalGroupedHitCount);
             assertEquals(1, results.Groups.Length);
-            GroupDocs<int> group = results.Groups[0];
+            IGroupDocs<int> group = results.Groups[0];
             Document childDoc = s.Doc(group.ScoreDocs[0].Doc);
             assertEquals("java", childDoc.Get("skill"));
             assertNotNull(group.GroupValue);
@@ -181,7 +181,7 @@ namespace Lucene.Net.Tests.Join
             assertEquals(1, results.TotalGroupedHitCount);
             assertEquals(1, results.Groups.Length);
 
-            GroupDocs<int> group = results.Groups[0];
+            IGroupDocs<int> group = results.Groups[0];
             assertEquals(1, group.TotalHits);
             assertFalse(float.IsNaN(group.Score));
 
@@ -835,10 +835,10 @@ namespace Lucene.Net.Tests.Join
                     Console.WriteLine("\nTEST: block join index gets " + (joinResults == null ? 0 : joinResults.Groups.Length) + " groups; hitsPerGroup=" + hitsPerGroup);
                     if (joinResults != null)
                     {
-                        GroupDocs<int>[] groups = joinResults.Groups;
+                        IGroupDocs<int>[] groups = joinResults.Groups;
                         for (int groupIDX = 0; groupIDX < groups.Length; groupIDX++)
                         {
-                            GroupDocs<int> group = groups[groupIDX];
+                            IGroupDocs<int> group = groups[groupIDX];
                             if (group.GroupSortValues != null)
                             {
                                 Console.Write("  ");
@@ -1084,11 +1084,11 @@ namespace Lucene.Net.Tests.Join
             int joinGroupUpto = 0;
 
             ScoreDoc[] hits = results.ScoreDocs;
-            GroupDocs<int>[] groupDocs = joinResults.Groups;
+            IGroupDocs<int>[] groupDocs = joinResults.Groups;
 
             while (joinGroupUpto < groupDocs.Length)
             {
-                GroupDocs<int> group = groupDocs[joinGroupUpto++];
+                IGroupDocs<int> group = groupDocs[joinGroupUpto++];
                 ScoreDoc[] groupHits = group.ScoreDocs;
                 assertNotNull(group.GroupValue);
                 Document parentDoc = joinR.Document(group.GroupValue);
@@ -1179,7 +1179,7 @@ namespace Lucene.Net.Tests.Join
             assertEquals(1, jobResults.TotalGroupedHitCount);
             assertEquals(1, jobResults.Groups.Length);
 
-            GroupDocs<int> group = jobResults.Groups[0];
+            IGroupDocs<int> group = jobResults.Groups[0];
             assertEquals(1, group.TotalHits);
 
             Document childJobDoc = s.Doc(group.ScoreDocs[0].Doc);
@@ -1195,7 +1195,7 @@ namespace Lucene.Net.Tests.Join
             assertEquals(1, qualificationResults.TotalGroupedHitCount);
             assertEquals(1, qualificationResults.Groups.Length);
 
-            GroupDocs<int> qGroup = qualificationResults.Groups[0];
+            IGroupDocs<int> qGroup = qualificationResults.Groups[0];
             assertEquals(1, qGroup.TotalHits);
 
             Document childQualificationDoc = s.Doc(qGroup.ScoreDocs[0].Doc);
@@ -1315,7 +1315,7 @@ namespace Lucene.Net.Tests.Join
                 assertEquals(2, results.TotalGroupedHitCount);
                 assertEquals(1, results.Groups.Length);
 
-                GroupDocs<int> resultGroup = results.Groups[0];
+                IGroupDocs<int> resultGroup = results.Groups[0];
                 assertEquals(2, resultGroup.TotalHits);
                 assertFalse(float.IsNaN(resultGroup.Score));
                 assertNotNull(resultGroup.GroupValue);
@@ -1339,7 +1339,7 @@ namespace Lucene.Net.Tests.Join
             assertEquals(2, boundedResults.TotalGroupedHitCount);
             assertEquals(1, boundedResults.Groups.Length);
 
-            GroupDocs<int> group = boundedResults.Groups[0];
+            IGroupDocs<int> group = boundedResults.Groups[0];
             assertEquals(2, group.TotalHits);
             assertFalse(float.IsNaN(group.Score));
             assertNotNull(group.GroupValue);
@@ -1413,7 +1413,7 @@ namespace Lucene.Net.Tests.Join
             // One child docs:
             assertEquals(1, groups.TotalGroupedHitCount);
 
-            GroupDocs<int> group = groups.Groups[0];
+            IGroupDocs<int> group = groups.Groups[0];
             Document doc = r.Document((int)group.GroupValue);
             assertEquals("0", doc.Get("parentID"));
 
@@ -1479,7 +1479,7 @@ namespace Lucene.Net.Tests.Join
             // One child docs:
             assertEquals(0, groups.TotalGroupedHitCount);
 
-            GroupDocs<int> group = groups.Groups[0];
+            IGroupDocs<int> group = groups.Groups[0];
             Document doc = r.Document((int)group.GroupValue);
             assertEquals("0", doc.Get("parentID"));
 


[21/58] [abbrv] lucenenet git commit: HACK: (3rd) Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context.

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs b/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
index eb92962..264e95c 100644
--- a/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
+++ b/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
@@ -529,6 +529,118 @@ namespace Lucene.Net.Support
                 return KeyComparer.GetHashCode(obj.Key) ^ ValueComparer.GetHashCode(obj.Value);
             }
         }
+
+
+        #region TestGenericCollection<TList, TItem>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestAddRemove()
+        {
+            base.TestAddRemove();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestAddReverseRemove()
+        {
+            base.TestAddReverseRemove();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestClear()
+        {
+            base.TestClear();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestContains()
+        {
+            base.TestContains();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestCopyTo()
+        {
+            base.TestCopyTo();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestIsReadOnly()
+        {
+            base.TestIsReadOnly();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestGetEnumerator()
+        {
+            base.TestGetEnumerator();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestGenericCollection_TestGetEnumerator2()
+        {
+            base.TestGetEnumerator2();
+        }
+
+        #endregion
+
+        #region TestCollection<TList, TFactory, TItem>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestAddRemove()
+        {
+            base.TestAddRemove();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestAddReverseRemove()
+        {
+            base.TestAddReverseRemove();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestClear()
+        {
+            base.TestClear();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestContains()
+        {
+            base.TestContains();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestCopyTo()
+        {
+            base.TestCopyTo();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestIsReadOnly()
+        {
+            base.TestIsReadOnly();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestGetEnumerator()
+        {
+            base.TestGetEnumerator();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestCollection_TestGetEnumerator2()
+        {
+            base.TestGetEnumerator2();
+        }
+
+        #endregion
+
     }
 
     [TestFixture]
@@ -553,6 +665,32 @@ namespace Lucene.Net.Support
             }
             return results.ToArray();
         }
+
+
+        #region TestDictionary<TDictionary, TFactory, TKey, TValue>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test, LuceneNetSpecific]
+        public void TestDictionary_TestAddRemoveByKey()
+        {
+            base.TestAddRemoveByKey();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestDictionary_TestKeys()
+        {
+            base.TestKeys();
+        }
+
+        [Test, LuceneNetSpecific]
+        public void TestDictionary_TestValues()
+        {
+            base.TestValues();
+        }
+
+        #endregion
     }
 
 
@@ -579,7 +717,7 @@ namespace Lucene.Net.Support
             return list;
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAddRemove()
         {
             TList list = new TList();
@@ -600,7 +738,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAddReverseRemove()
         {
             TList list = new TList();
@@ -621,7 +759,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestClear()
         {
             TList list = new TList();
@@ -636,7 +774,7 @@ namespace Lucene.Net.Support
             Assert.AreEqual(0, list.Count);
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestContains()
         {
             TList list = new TList();
@@ -650,7 +788,7 @@ namespace Lucene.Net.Support
                 Assert.IsTrue(list.Contains(item));
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestCopyTo()
         {
             TList list = new TList();
@@ -670,13 +808,13 @@ namespace Lucene.Net.Support
             Assert.AreEqual(0, items.Count);
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestIsReadOnly()
         {
             Assert.IsFalse(new TList().IsReadOnly);
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestGetEnumerator()
         {
             TList list = new TList();
@@ -692,7 +830,7 @@ namespace Lucene.Net.Support
             Assert.AreEqual(0, items.Count);
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestGetEnumerator2()
         {
             TList list = new TList();
@@ -758,7 +896,7 @@ namespace Lucene.Net.Support
         where TDictionary : IDictionary<TKey, TValue>, IDisposable
         where TFactory : IFactory<TDictionary>, new()
     {
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAddRemoveByKey()
         {
             KeyValuePair<TKey, TValue>[] sample = GetSample();
@@ -780,7 +918,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestKeys()
         {
             KeyValuePair<TKey, TValue>[] sample = GetSample();
@@ -803,7 +941,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestValues()
         {
             KeyValuePair<TKey, TValue>[] sample = GetSample();
@@ -832,7 +970,7 @@ namespace Lucene.Net.Support
 
         protected readonly TFactory Factory = new TFactory();
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAddRemove()
         {
             using (TList list = Factory.Create())
@@ -855,7 +993,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAddReverseRemove()
         {
             using (TList list = Factory.Create())
@@ -878,7 +1016,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestClear()
         {
             using (TList list = Factory.Create())
@@ -895,7 +1033,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestContains()
         {
             using (TList list = Factory.Create())
@@ -911,7 +1049,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestCopyTo()
         {
             using (TList list = Factory.Create())
@@ -933,14 +1071,14 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestIsReadOnly()
         {
             using (TList list = Factory.Create())
                 Assert.IsFalse(list.IsReadOnly);
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestGetEnumerator()
         {
             using (TList list = Factory.Create())
@@ -958,7 +1096,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test, LuceneNetSpecific]
+        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestGetEnumerator2()
         {
             using (TList list = Factory.Create())

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs b/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
index dd31909..51ac7e2 100644
--- a/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
+++ b/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
@@ -153,55 +153,55 @@ namespace Lucene.Net.Util
             DoTest(strategy, Random().Next(20000));
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestEmpty()
         {
             SortTest(new Entry[0]);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestOne()
         {
             DoTest(RandomStrategy, 1);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwo()
         {
             DoTest(RandomStrategy, 2);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestRandom()
         {
             DoTest(RandomStrategy);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestRandomLowCardinality()
         {
             DoTest(RandomLowCardinalityStrategy, 2);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAscending()
         {
             DoTest(AscendingStrategy, 2);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestAscendingSequences()
         {
             DoTest(AscendingSequencesStrategy, 2);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDescending()
         {
             DoTest(DescendingStrategy, 2);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestStrictlyDescendingStrategy()
         {
             DoTest(StrictlyDescendingStrategy, 2);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs b/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
index 91c7062..38d63a1 100644
--- a/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
@@ -1,4 +1,5 @@
 using Lucene.Net.Support;
+using NUnit.Framework;
 using System.Collections;
 using System.Diagnostics;
 
@@ -75,5 +76,49 @@ namespace Lucene.Net.Util.Packed
                 return SlowAdvance(target);
             }
         }
+
+
+        #region BaseDocIdSetTestCase<T>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// Test length=0.
+        /// </summary>
+        [Test]
+        public override void TestNoBit()
+        {
+            base.TestNoBit();
+        }
+
+        /// <summary>
+        /// Test length=1.
+        /// </summary>
+        [Test]
+        public override void Test1Bit()
+        {
+            base.Test1Bit();
+        }
+
+        /// <summary>
+        /// Test length=2.
+        /// </summary>
+        [Test]
+        public override void Test2Bits()
+        {
+            base.Test2Bits();
+        }
+
+        /// <summary>
+        /// Compare the content of the set against a <seealso cref="BitSet"/>.
+        /// </summary>
+        [Test]
+        public override void TestAgainstBitSet()
+        {
+            base.TestAgainstBitSet();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs b/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
index 1294bff..bb779c5 100644
--- a/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
@@ -1,3 +1,5 @@
+using Lucene.Net.Attributes;
+using NUnit.Framework;
 using System.Collections;
 
 namespace Lucene.Net.Util
@@ -25,5 +27,49 @@ namespace Lucene.Net.Util
         {
             return new DocIdBitSet((BitArray)bs.Clone());
         }
+
+
+        #region BaseDocIdSetTestCase<T>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// Test length=0.
+        /// </summary>
+        [Test]
+        public override void TestNoBit()
+        {
+            base.TestNoBit();
+        }
+
+        /// <summary>
+        /// Test length=1.
+        /// </summary>
+        [Test]
+        public override void Test1Bit()
+        {
+            base.Test1Bit();
+        }
+
+        /// <summary>
+        /// Test length=2.
+        /// </summary>
+        [Test]
+        public override void Test2Bits()
+        {
+            base.Test2Bits();
+        }
+
+        /// <summary>
+        /// Compare the content of the set against a <seealso cref="BitSet"/>.
+        /// </summary>
+        [Test, LongRunningTest, Timeout(150000)]
+        public override void TestAgainstBitSet()
+        {
+            base.TestAgainstBitSet();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs b/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
index 550b3e1..2f822f9 100644
--- a/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
@@ -1,4 +1,5 @@
 using System;
+using Lucene.Net.Attributes;
 using Lucene.Net.Randomized.Generators;
 using Lucene.Net.Support;
 using NUnit.Framework;
@@ -510,5 +511,49 @@ namespace Lucene.Net.Util
             Assert.IsTrue(bits.Get(1));
             Assert.IsFalse(newBits.Get(1));
         }
+
+
+        #region BaseDocIdSetTestCase<T>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// Test length=0.
+        /// </summary>
+        [Test]
+        public override void TestNoBit()
+        {
+            base.TestNoBit();
+        }
+
+        /// <summary>
+        /// Test length=1.
+        /// </summary>
+        [Test]
+        public override void Test1Bit()
+        {
+            base.Test1Bit();
+        }
+
+        /// <summary>
+        /// Test length=2.
+        /// </summary>
+        [Test]
+        public override void Test2Bits()
+        {
+            base.Test2Bits();
+        }
+
+        /// <summary>
+        /// Compare the content of the set against a <seealso cref="BitSet"/>.
+        /// </summary>
+        [Test, LongRunningTest, Timeout(150000)]
+        public override void TestAgainstBitSet()
+        {
+            base.TestAgainstBitSet();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs b/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
index 5c35706..3649531 100644
--- a/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Util
 {
     /*
@@ -32,5 +34,67 @@ namespace Lucene.Net.Util
         {
             return new ArrayInPlaceMergeSorter<Entry>(arr, ArrayUtil.naturalComparator<Entry>());
         }
+
+
+        #region BaseSortTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestEmpty()
+        {
+            base.TestEmpty();
+        }
+
+        [Test]
+        public override void TestOne()
+        {
+            base.TestOne();
+        }
+
+        [Test]
+        public override void TestTwo()
+        {
+            base.TestTwo();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestRandomLowCardinality()
+        {
+            base.TestRandomLowCardinality();
+        }
+
+        [Test]
+        public override void TestAscending()
+        {
+            base.TestAscending();
+        }
+
+        [Test]
+        public override void TestAscendingSequences()
+        {
+            base.TestAscendingSequences();
+        }
+
+        [Test]
+        public override void TestDescending()
+        {
+            base.TestDescending();
+        }
+
+        [Test]
+        public override void TestStrictlyDescendingStrategy()
+        {
+            base.TestStrictlyDescendingStrategy();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs b/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
index c71893a..b2c75f8 100644
--- a/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Util
 {
     /*
@@ -28,5 +30,67 @@ namespace Lucene.Net.Util
         {
             return new ArrayIntroSorter<Entry>(arr, ArrayUtil.naturalComparator<Entry>());
         }
+
+
+        #region BaseSortTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestEmpty()
+        {
+            base.TestEmpty();
+        }
+
+        [Test]
+        public override void TestOne()
+        {
+            base.TestOne();
+        }
+
+        [Test]
+        public override void TestTwo()
+        {
+            base.TestTwo();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestRandomLowCardinality()
+        {
+            base.TestRandomLowCardinality();
+        }
+
+        [Test]
+        public override void TestAscending()
+        {
+            base.TestAscending();
+        }
+
+        [Test]
+        public override void TestAscendingSequences()
+        {
+            base.TestAscendingSequences();
+        }
+
+        [Test]
+        public override void TestDescending()
+        {
+            base.TestDescending();
+        }
+
+        [Test]
+        public override void TestStrictlyDescendingStrategy()
+        {
+            base.TestStrictlyDescendingStrategy();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs b/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
index c72aa45..8144d1c 100644
--- a/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
@@ -514,5 +514,49 @@ namespace Lucene.Net.Util
             bits.FastSet(bit - 1);
             Assert.IsTrue(bits.FastGet(bit - 1));
         }
+
+
+        #region BaseDocIdSetTestCase<T>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// Test length=0.
+        /// </summary>
+        [Test]
+        public override void TestNoBit()
+        {
+            base.TestNoBit();
+        }
+
+        /// <summary>
+        /// Test length=1.
+        /// </summary>
+        [Test]
+        public override void Test1Bit()
+        {
+            base.Test1Bit();
+        }
+
+        /// <summary>
+        /// Test length=2.
+        /// </summary>
+        [Test]
+        public override void Test2Bits()
+        {
+            base.Test2Bits();
+        }
+
+        /// <summary>
+        /// Compare the content of the set against a <seealso cref="BitSet"/>.
+        /// </summary>
+        [Test, LongRunningTest, Timeout(150000)]
+        public override void TestAgainstBitSet()
+        {
+            base.TestAgainstBitSet();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs b/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
index 3c92150..b310b7b 100644
--- a/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
@@ -38,5 +38,49 @@ namespace Lucene.Net.Util
             base.AssertEquals(numBits, ds1, ds2);
             Assert.AreEqual(ds1.Cardinality(), ds2.Cardinality());
         }
+
+
+        #region BaseDocIdSetTestCase<T>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// Test length=0.
+        /// </summary>
+        [Test]
+        public override void TestNoBit()
+        {
+            base.TestNoBit();
+        }
+
+        /// <summary>
+        /// Test length=1.
+        /// </summary>
+        [Test]
+        public override void Test1Bit()
+        {
+            base.Test1Bit();
+        }
+
+        /// <summary>
+        /// Test length=2.
+        /// </summary>
+        [Test]
+        public override void Test2Bits()
+        {
+            base.Test2Bits();
+        }
+
+        /// <summary>
+        /// Compare the content of the set against a <seealso cref="BitSet"/>.
+        /// </summary>
+        [Test]
+        public override void TestAgainstBitSet()
+        {
+            base.TestAgainstBitSet();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs b/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
index c12b850..8f13308 100644
--- a/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Util
 {
     /*
@@ -28,5 +30,67 @@ namespace Lucene.Net.Util
         {
             return new ArrayTimSorter<Entry>(arr, ArrayUtil.naturalComparator<Entry>(), TestUtil.NextInt(Random(), 0, arr.Length));
         }
+
+
+        #region BaseSortTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestEmpty()
+        {
+            base.TestEmpty();
+        }
+
+        [Test]
+        public override void TestOne()
+        {
+            base.TestOne();
+        }
+
+        [Test]
+        public override void TestTwo()
+        {
+            base.TestTwo();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestRandomLowCardinality()
+        {
+            base.TestRandomLowCardinality();
+        }
+
+        [Test]
+        public override void TestAscending()
+        {
+            base.TestAscending();
+        }
+
+        [Test]
+        public override void TestAscendingSequences()
+        {
+            base.TestAscendingSequences();
+        }
+
+        [Test]
+        public override void TestDescending()
+        {
+            base.TestDescending();
+        }
+
+        [Test]
+        public override void TestStrictlyDescendingStrategy()
+        {
+            base.TestStrictlyDescendingStrategy();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs b/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
index 73d338d..b0d3ea0 100644
--- a/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
@@ -106,5 +106,49 @@ namespace Lucene.Net.Util
             }
             AssertEquals(numBits, expected, union);
         }
+
+
+        #region BaseDocIdSetTestCase<T>
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// Test length=0.
+        /// </summary>
+        [Test]
+        public override void TestNoBit()
+        {
+            base.TestNoBit();
+        }
+
+        /// <summary>
+        /// Test length=1.
+        /// </summary>
+        [Test]
+        public override void Test1Bit()
+        {
+            base.Test1Bit();
+        }
+
+        /// <summary>
+        /// Test length=2.
+        /// </summary>
+        [Test]
+        public override void Test2Bits()
+        {
+            base.Test2Bits();
+        }
+
+        /// <summary>
+        /// Compare the content of the set against a <seealso cref="BitSet"/>.
+        /// </summary>
+        [Test]
+        public override void TestAgainstBitSet()
+        {
+            base.TestAgainstBitSet();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file


[33/58] [abbrv] lucenenet git commit: WIP on Grouping

Posted by ni...@apache.org.
WIP on Grouping


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

Branch: refs/heads/grouping
Commit: 9d72bcb3469dedd6bac66c3ee82bfc38e80e0eba
Parents: c3abdc7
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Oct 27 14:07:36 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:53 2016 +0700

----------------------------------------------------------------------
 Lucene.Net.sln                                  |   14 +
 src/Lucene.Net.Core/Search/TopDocsCollector.cs  |   22 +-
 .../AbstractAllGroupHeadsCollector.cs           |  245 +++
 .../AbstractAllGroupsCollector.cs               |   85 +
 .../AbstractDistinctValuesCollector.cs          |   89 +
 .../AbstractFirstPassGroupingCollector.cs       |  427 +++++
 .../AbstractGroupFacetCollector.cs              |  375 ++++
 .../AbstractSecondPassGroupingCollector.cs      |  170 ++
 .../BlockGroupingCollector.cs                   |  601 +++++++
 src/Lucene.Net.Grouping/CollectedSearchGroup.cs |   31 +
 .../Function/FunctionAllGroupHeadsCollector.cs  |  155 ++
 .../Function/FunctionAllGroupsCollector.cs      |   69 +
 .../Function/FunctionDistinctValuesCollector.cs |   85 +
 .../FunctionFirstPassGroupingCollector.cs       |   71 +
 .../FunctionSecondPassGroupingCollector.cs      |   64 +
 src/Lucene.Net.Grouping/GroupDocs.cs            |    8 +-
 src/Lucene.Net.Grouping/GroupingSearch.cs       |  483 +++++
 .../Lucene.Net.Grouping.csproj                  |   26 +
 src/Lucene.Net.Grouping/SearchGroup.cs          |  388 ++++
 .../Term/TermAllGroupHeadsCollector.cs          |  807 +++++++++
 .../Term/TermAllGroupsCollector.cs              |  120 ++
 .../Term/TermDistinctValuesCollector.cs         |  144 ++
 .../Term/TermFirstPassGroupingCollector.cs      |   88 +
 .../Term/TermGroupFacetCollector.cs             |  444 +++++
 .../Term/TermSecondPassGroupingCollector.cs     |   65 +
 src/Lucene.Net.Grouping/TopGroups.cs            |   11 +-
 .../AbstractGroupingTestCase.cs                 |   30 +
 .../AllGroupHeadsCollectorTest.cs               |  718 ++++++++
 .../AllGroupsCollectorTest.cs                   |  138 ++
 .../DistinctValuesCollectorTest.cs              |  648 +++++++
 .../GroupFacetCollectorTest.cs                  |  943 ++++++++++
 .../GroupingSearchTest.cs                       |  245 +++
 .../Lucene.Net.Tests.Grouping.csproj            |   85 +
 .../Properties/AssemblyInfo.cs                  |   36 +
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs   | 1692 ++++++++++++++++++
 src/Lucene.Net.Tests.Grouping/packages.config   |    4 +
 36 files changed, 9615 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/Lucene.Net.sln
----------------------------------------------------------------------
diff --git a/Lucene.Net.sln b/Lucene.Net.sln
index c87a7be..7591ffc 100644
--- a/Lucene.Net.sln
+++ b/Lucene.Net.sln
@@ -68,6 +68,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Analysis.Stempel
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Analysis.Stempel", "src\Lucene.Net.Tests.Analysis.Stempel\Lucene.Net.Tests.Analysis.Stempel.csproj", "{940A6AB1-F00A-40E2-BC1A-2898EFA8C48F}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Grouping", "src\Lucene.Net.Tests.Grouping\Lucene.Net.Tests.Grouping.csproj", "{C2349F0D-FB66-4544-9C33-4D87F73C6004}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -383,6 +385,18 @@ Global
 		{940A6AB1-F00A-40E2-BC1A-2898EFA8C48F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 		{940A6AB1-F00A-40E2-BC1A-2898EFA8C48F}.Release|x86.ActiveCfg = Release|Any CPU
 		{940A6AB1-F00A-40E2-BC1A-2898EFA8C48F}.Release|x86.Build.0 = Release|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Debug|x86.Build.0 = Debug|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Release|x86.ActiveCfg = Release|Any CPU
+		{C2349F0D-FB66-4544-9C33-4D87F73C6004}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Core/Search/TopDocsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Search/TopDocsCollector.cs b/src/Lucene.Net.Core/Search/TopDocsCollector.cs
index 3b28e63..ccfa2a6 100644
--- a/src/Lucene.Net.Core/Search/TopDocsCollector.cs
+++ b/src/Lucene.Net.Core/Search/TopDocsCollector.cs
@@ -1,4 +1,5 @@
 using System;
+using Lucene.Net.Index;
 
 namespace Lucene.Net.Search
 {
@@ -32,7 +33,7 @@ namespace Lucene.Net.Search
     /// however, you might want to consider overriding all methods, in order to avoid
     /// a NullPointerException.
     /// </summary>
-    public abstract class TopDocsCollector<T> : Collector where T : ScoreDoc
+    public abstract class TopDocsCollector<T> : Collector, ITopDocsCollector where T : ScoreDoc
     {
         /// <summary>
         /// this is used in case topDocs() is called with illegal parameters, or there
@@ -185,4 +186,23 @@ namespace Lucene.Net.Search
             return NewTopDocs(results, start);
         }
     }
+
+    /// <summary>
+    /// LUCENENET specific interface used to reference <see cref="TopDocsCollector{T}"/>
+    /// without referencing its generic type.
+    /// </summary>
+    public interface ITopDocsCollector
+    {
+        // From TopDocsCollector<T>
+        int TotalHits { get; set; }
+        TopDocs TopDocs();
+        TopDocs TopDocs(int start);
+        TopDocs TopDocs(int start, int howMany);
+
+        // From Collector
+        Scorer Scorer { set; }
+        void Collect(int doc);
+        AtomicReaderContext NextReader { set; }
+        bool AcceptsDocsOutOfOrder();
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
new file mode 100644
index 0000000..a3ae1bf
--- /dev/null
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -0,0 +1,245 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    public abstract class AbstractAllGroupHeadsCollector<GH> : AbstractAllGroupHeadsCollector
+        where GH : AbstractGroupHead /*AbstractAllGroupHeadsCollector<GH>.GroupHead*/
+    {
+        protected readonly int[] reversed;
+        protected readonly int compIDXEnd;
+        protected readonly TemporalResult temporalResult;
+
+        protected AbstractAllGroupHeadsCollector(int numberOfSorts)
+        {
+            this.reversed = new int[numberOfSorts];
+            this.compIDXEnd = numberOfSorts - 1;
+            temporalResult = new TemporalResult();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="maxDoc">The maxDoc of the top level <see cref="Index.IndexReader"/></param>
+        /// <returns>a <see cref="FixedBitSet"/> containing all group heads.</returns>
+        public override FixedBitSet RetrieveGroupHeads(int maxDoc)
+        {
+            FixedBitSet bitSet = new FixedBitSet(maxDoc);
+
+            ICollection<GH> groupHeads = GetCollectedGroupHeads();
+            foreach (GH groupHead in groupHeads)
+            {
+                bitSet.Set(groupHead.Doc);
+            }
+
+            return bitSet;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>an int array containing all group heads. The size of the array is equal to number of collected unique groups.</returns>
+        public override int[] RetrieveGroupHeads()
+        {
+            ICollection<GH> groupHeads = GetCollectedGroupHeads();
+            int[] docHeads = new int[groupHeads.Count];
+
+            int i = 0;
+            foreach (GH groupHead in groupHeads)
+            {
+                docHeads[i++] = groupHead.Doc;
+            }
+
+            return docHeads;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the number of group heads found for a query.</returns>
+        public override int GroupHeadsSize
+        {
+            get
+            {
+                return GetCollectedGroupHeads().Count;
+            }
+        }
+
+        /// <summary>
+        /// Returns the group head and puts it into <see cref="TemporalResult"/>.
+        /// If the group head wasn't encountered before then it will be added to the collected group heads.
+        /// <para>
+        /// The <see cref="TemporalResult.stop"/> property will be <c>true</c> if the group head wasn't encountered before
+        /// otherwise <c>false</c>.
+        /// </para>
+        /// </summary>
+        /// <param name="doc">The document to retrieve the group head for.</param>
+        /// <exception cref="IOException">If I/O related errors occur</exception>
+        protected override abstract void RetrieveGroupHeadAndAddIfNotExist(int doc);
+
+        /// <summary>
+        /// Returns the collected group heads.
+        /// Subsequent calls should return the same group heads.
+        /// </summary>
+        /// <returns>the collected group heads</returns>
+        protected abstract ICollection<GH> GetCollectedGroupHeads();
+
+        public override void Collect(int doc)
+        {
+            RetrieveGroupHeadAndAddIfNotExist(doc);
+            if (temporalResult.stop)
+            {
+                return;
+            }
+            GH groupHead = temporalResult.groupHead;
+
+            // Ok now we need to check if the current doc is more relevant then current doc for this group
+            for (int compIDX = 0; ; compIDX++)
+            {
+                int c = reversed[compIDX] * groupHead.Compare(compIDX, doc);
+                if (c < 0)
+                {
+                    // Definitely not competitive. So don't even bother to continue
+                    return;
+                }
+                else if (c > 0)
+                {
+                    // Definitely competitive.
+                    break;
+                }
+                else if (compIDX == compIDXEnd)
+                {
+                    // Here c=0. If we're at the last comparator, this doc is not
+                    // competitive, since docs are visited in doc Id order, which means
+                    // this doc cannot compete with any other document in the queue.
+                    return;
+                }
+            }
+            groupHead.UpdateDocHead(doc);
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return false;
+        }
+
+        /// <summary>
+        /// Contains the result of group head retrieval.
+        /// To prevent new object creations of this class for every collect.
+        /// </summary>
+        public class TemporalResult
+        {
+
+            public GH groupHead;
+            public bool stop;
+
+        }
+    }
+
+    /// <summary>
+    /// Represents a group head. A group head is the most relevant document for a particular group.
+    /// The relevancy is based is usually based on the sort.
+    /// <para>
+    /// The group head contains a group value with its associated most relevant document id.
+    /// </para>
+    /// </summary>
+    /// <remarks>
+    /// LUCENENET: moved this class outside of the AbstractAllGroupHeadsCollector,
+    /// made non-generic, and renamed from GroupHead to AbstractGroupHead.
+    /// </remarks>
+    public abstract class AbstractGroupHead /*<TGroupValue>*/
+    {
+
+        //public readonly TGroupValue groupValue;
+        public int Doc { get; protected set; }
+
+        protected AbstractGroupHead(/*TGroupValue groupValue,*/ int doc)
+        {
+            //this.groupValue = groupValue;
+            this.Doc = doc;
+        }
+
+        /// <summary>
+        /// Compares the specified document for a specified comparator against the current most relevant document.
+        /// </summary>
+        /// <param name="compIDX">The comparator index of the specified comparator.</param>
+        /// <param name="doc">The specified document.</param>
+        /// <returns>
+        /// -1 if the specified document wasn't competitive against the current most relevant document, 1 if the
+        /// specified document was competitive against the current most relevant document. Otherwise 0.
+        /// </returns>
+        /// <exception cref="IOException">If I/O related errors occur</exception>
+        public abstract int Compare(int compIDX, int doc);
+
+        /// <summary>
+        /// Updates the current most relevant document with the specified document.
+        /// </summary>
+        /// <param name="doc">The specified document</param>
+        /// <exception cref="IOException">If I/O related errors occur</exception>
+        public abstract void UpdateDocHead(int doc);
+    }
+
+    /// <summary>
+    /// LUCENENET specific class used to reference an 
+    /// <see cref="AbstractAllGroupHeadsCollector{GH}"/> subclass
+    /// without refering to its generic closing type.
+    /// </summary>
+    public abstract class AbstractAllGroupHeadsCollector : Collector
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="maxDoc">The maxDoc of the top level <see cref="Index.IndexReader"/></param>
+        /// <returns>a <see cref="FixedBitSet"/> containing all group heads.</returns>
+        public abstract FixedBitSet RetrieveGroupHeads(int maxDoc);
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>an int array containing all group heads. The size of the array is equal to number of collected unique groups.</returns>
+        public abstract int[] RetrieveGroupHeads();
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns>the number of group heads found for a query.</returns>
+        public abstract int GroupHeadsSize { get; }
+
+        /// <summary>
+        /// Returns the group head and puts it into <see cref="TemporalResult"/>.
+        /// If the group head wasn't encountered before then it will be added to the collected group heads.
+        /// <para>
+        /// The <see cref="TemporalResult.stop"/> property will be <c>true</c> if the group head wasn't encountered before
+        /// otherwise <c>false</c>.
+        /// </para>
+        /// </summary>
+        /// <param name="doc">The document to retrieve the group head for.</param>
+        /// <exception cref="IOException">If I/O related errors occur</exception>
+        protected abstract void RetrieveGroupHeadAndAddIfNotExist(int doc);
+    }
+
+    /////// <summary>
+    /////// LUCENENET specific interface used to reference an 
+    /////// <see cref="AbstractAllGroupHeadsCollector{GH}"/> subclass
+    /////// without refering to its generic closing type.
+    /////// </summary>
+    ////public interface IAllGroupHeadsCollector
+    ////{
+    ////    // From AbstractAllGroupHeadsCollector{GH}
+    ////    FixedBitSet RetrieveGroupHeads(int maxDoc);
+    ////    int[] RetrieveGroupHeads();
+    ////    int GroupHeadsSize { get; }
+    ////    void Collect(int doc);
+    ////    bool AcceptsDocsOutOfOrder();
+
+    ////    // From Collector
+    ////    Scorer Scorer { set; }
+    ////    AtomicReaderContext NextReader { set; }
+    ////}
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
new file mode 100644
index 0000000..0c8bc14
--- /dev/null
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
@@ -0,0 +1,85 @@
+\ufeffusing System.Collections.Generic;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// A collector that collects all groups that match the
+    /// query. Only the group value is collected, and the order
+    /// is undefined.  This collector does not determine
+    /// the most relevant document of a group.
+    /// 
+    /// <para>
+    /// This is an abstract version. Concrete implementations define
+    /// what a group actually is and how it is internally collected.
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public abstract class AbstractAllGroupsCollector<TGroupValue> : AbstractAllGroupsCollector
+    {
+        /// <summary>
+        /// Returns the total number of groups for the executed search.
+        /// This is a convenience method. The following code snippet has the same effect: <code>GetGroups().Count</code>
+        /// </summary>
+        /// <returns>The total number of groups for the executed search</returns>
+        public override int GroupCount
+        {
+            get
+            {
+                return Groups.Count;
+            }
+        }
+
+        /// <summary>
+        /// Returns the group values
+        /// <para>
+        /// This is an unordered collections of group values. For each group that matched the query there is a <see cref="BytesRef"/>
+        /// representing a group value.
+        /// </para>
+        /// </summary>
+        /// <returns>the group values</returns>
+        public abstract ICollection<TGroupValue> Groups { get; }
+
+
+        // Empty not necessary
+        public override Scorer Scorer
+        {
+            set
+            {
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return true;
+        }
+    }
+
+    /// <summary>
+    /// LUCENENET specific class used to reference <see cref="AbstractAllGroupsCollector{TGroupValue}"/>
+    /// without refering to its generic closing type.
+    /// </summary>
+    public abstract class AbstractAllGroupsCollector : Collector
+    {
+        /// <summary>
+        /// Returns the total number of groups for the executed search.
+        /// This is a convenience method. The following code snippet has the same effect: <code>GetGroups().Count</code>
+        /// </summary>
+        /// <returns>The total number of groups for the executed search</returns>
+        public abstract int GroupCount { get; }
+
+
+        // Empty not necessary
+        public override Scorer Scorer
+        {
+            set
+            {
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return true;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
new file mode 100644
index 0000000..e9df8d8
--- /dev/null
+++ b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
@@ -0,0 +1,89 @@
+\ufeffusing Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// A second pass grouping collector that keeps track of distinct values for a specified field for the top N group.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="GC"></typeparam>
+    public abstract class AbstractDistinctValuesCollector<GC> : Collector where GC : IGroupCount /* AbstractDistinctValuesCollector<GC>.GroupCount */
+    {
+        /// <summary>
+        /// Returns all unique values for each top N group.
+        /// </summary>
+        /// <returns>all unique values for each top N group</returns>
+        public abstract List<GC> GetGroups();
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return true;
+        }
+
+        public override Scorer Scorer
+        {
+            set
+            {
+            }
+        } 
+    }
+
+    //public abstract class AbstractDistinctValuesCollector : Collector
+    //{
+    //    /// <summary>
+    //    /// Returns all unique values for each top N group.
+    //    /// </summary>
+    //    /// <returns>all unique values for each top N group</returns>
+    //    public abstract List<GC> GetGroups();
+
+    //    public override bool AcceptsDocsOutOfOrder()
+    //    {
+    //        return true;
+    //    }
+
+    //    public override Scorer Scorer
+    //    {
+    //        set
+    //        {
+    //        }
+    //    }
+    //}
+
+
+    /// <summary>
+    /// Returned by <see cref="AbstractDistinctValuesCollector.GetGroups()"/>,
+    /// representing the value and set of distinct values for the group.
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    /// <remarks>
+    /// LUCENENET - removed this class from being a nested class of 
+    /// <see cref="AbstractDistinctValuesCollector{GC}"/> and renamed
+    /// from GroupCount to AbstractGroupCount
+    /// </remarks>
+    public abstract class AbstractGroupCount<TGroupValue> : IGroupCount
+        //where TGroupValue : IComparable
+    {
+        public readonly TGroupValue groupValue;
+        public readonly ISet<TGroupValue> uniqueValues;
+
+        public AbstractGroupCount(TGroupValue groupValue)
+        {
+            this.groupValue = groupValue;
+            this.uniqueValues = new HashSet<TGroupValue>();
+        }
+    }
+
+    /// <summary>
+    /// LUCENENET specific interface to allow usage of <see cref="AbstractGroupCount{TGroupValue}"/>
+    /// as a generic closing type without having to specify TGroupValue.
+    /// </summary>
+    public interface IGroupCount
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
new file mode 100644
index 0000000..8efafd2
--- /dev/null
+++ b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
@@ -0,0 +1,427 @@
+\ufeffusing Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Lucene.Net.Index;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// FirstPassGroupingCollector is the first of two passes necessary
+    /// to collect grouped hits.  This pass gathers the top N sorted
+    /// groups. Concrete subclasses define what a group is and how it
+    /// is internally collected.
+    /// 
+    /// <para>
+    /// See {@link org.apache.lucene.search.grouping} for more
+    /// details including a full code example.
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public abstract class AbstractFirstPassGroupingCollector<TGroupValue> : Collector
+    {
+        private readonly Sort groupSort;
+        private readonly FieldComparator[] comparators;
+        private readonly int[] reversed;
+        private readonly int topNGroups;
+        private readonly IDictionary<TGroupValue, CollectedSearchGroup<TGroupValue>> groupMap;
+        private readonly int compIDXEnd;
+
+        // Set once we reach topNGroups unique groups:
+        // @lucene.internal
+        protected SortedSet<CollectedSearchGroup<TGroupValue>> orderedGroups;
+        private int docBase;
+        private int spareSlot;
+
+        /// <summary>
+        /// Create the first pass collector.
+        /// </summary>
+        /// <param name="groupSort">
+        /// The {@link Sort} used to sort the
+        /// groups.  The top sorted document within each group
+        /// according to groupSort, determines how that group
+        /// sorts against other groups.  This must be non-null,
+        /// ie, if you want to groupSort by relevance use
+        /// Sort.RELEVANCE.
+        /// </param>
+        /// <param name="topNGroups">How many top groups to keep.</param>
+        /// <exception cref="IOException">If I/O related errors occur</exception>
+        public AbstractFirstPassGroupingCollector(Sort groupSort, int topNGroups)
+        {
+            if (topNGroups < 1)
+            {
+                throw new ArgumentException("topNGroups must be >= 1 (got " + topNGroups + ")");
+            }
+
+            // TODO: allow null groupSort to mean "by relevance",
+            // and specialize it?
+            this.groupSort = groupSort;
+
+            this.topNGroups = topNGroups;
+
+            SortField[] sortFields = groupSort.GetSort();
+            comparators = new FieldComparator[sortFields.Length];
+            compIDXEnd = comparators.Length - 1;
+            reversed = new int[sortFields.Length];
+            for (int i = 0; i < sortFields.Length; i++)
+            {
+                SortField sortField = sortFields[i];
+
+                // use topNGroups + 1 so we have a spare slot to use for comparing (tracked by this.spareSlot):
+                comparators[i] = sortField.GetComparator(topNGroups + 1, i);
+                reversed[i] = sortField.Reverse ? -1 : 1;
+            }
+
+            spareSlot = topNGroups;
+            groupMap = new Dictionary<TGroupValue, CollectedSearchGroup<TGroupValue>>(topNGroups);
+        }
+
+        /// <summary>
+        /// Returns top groups, starting from offset.  This may
+        /// return null, if no groups were collected, or if the
+        /// number of unique groups collected is &lt;= offset.
+        /// </summary>
+        /// <param name="groupOffset">The offset in the collected groups</param>
+        /// <param name="fillFields">Whether to fill to <see cref="SearchGroup.sortValues"/></param>
+        /// <returns>top groups, starting from offset</returns>
+        public ICollection<SearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields)
+        {
+
+            //System.out.println("FP.getTopGroups groupOffset=" + groupOffset + " fillFields=" + fillFields + " groupMap.size()=" + groupMap.size());
+
+            if (groupOffset < 0)
+            {
+                throw new ArgumentException("groupOffset must be >= 0 (got " + groupOffset + ")");
+            }
+
+            if (groupMap.Count <= groupOffset)
+            {
+                return null;
+            }
+
+            if (orderedGroups == null)
+            {
+                BuildSortedSet();
+            }
+
+            ICollection<SearchGroup<TGroupValue>> result = new List<SearchGroup<TGroupValue>>();
+            int upto = 0;
+            int sortFieldCount = groupSort.GetSort().Length;
+            foreach (CollectedSearchGroup<TGroupValue> group in orderedGroups)
+            {
+                if (upto++ < groupOffset)
+                {
+                    continue;
+                }
+                //System.out.println("  group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
+                SearchGroup<TGroupValue> searchGroup = new SearchGroup<TGroupValue>();
+                searchGroup.groupValue = group.groupValue;
+                if (fillFields)
+                {
+                    searchGroup.sortValues = new object[sortFieldCount];
+                    for (int sortFieldIDX = 0; sortFieldIDX < sortFieldCount; sortFieldIDX++)
+                    {
+                        searchGroup.sortValues[sortFieldIDX] = comparators[sortFieldIDX].Value(group.ComparatorSlot);
+                    }
+                }
+                result.Add(searchGroup);
+            }
+            //System.out.println("  return " + result.size() + " groups");
+            return result;
+        }
+
+        public override Scorer Scorer
+        {
+            set
+            {
+                foreach (FieldComparator comparator in comparators)
+                {
+                    comparator.Scorer = value;
+                }
+            }
+        }
+
+        public override void Collect(int doc)
+        {
+            //System.out.println("FP.collect doc=" + doc);
+
+            // If orderedGroups != null we already have collected N groups and
+            // can short circuit by comparing this document to the bottom group,
+            // without having to find what group this document belongs to.
+
+            // Even if this document belongs to a group in the top N, we'll know that
+            // we don't have to update that group.
+
+            // Downside: if the number of unique groups is very low, this is
+            // wasted effort as we will most likely be updating an existing group.
+            if (orderedGroups != null)
+            {
+                for (int compIDX = 0; ; compIDX++)
+                {
+                    int c = reversed[compIDX] * comparators[compIDX].CompareBottom(doc);
+                    if (c < 0)
+                    {
+                        // Definitely not competitive. So don't even bother to continue
+                        return;
+                    }
+                    else if (c > 0)
+                    {
+                        // Definitely competitive.
+                        break;
+                    }
+                    else if (compIDX == compIDXEnd)
+                    {
+                        // Here c=0. If we're at the last comparator, this doc is not
+                        // competitive, since docs are visited in doc Id order, which means
+                        // this doc cannot compete with any other document in the queue.
+                        return;
+                    }
+                }
+            }
+
+            // TODO: should we add option to mean "ignore docs that
+            // don't have the group field" (instead of stuffing them
+            // under null group)?
+            TGroupValue groupValue = GetDocGroupValue(doc);
+
+            CollectedSearchGroup<TGroupValue> group = groupMap[groupValue];
+
+            if (group == null)
+            {
+
+                // First time we are seeing this group, or, we've seen
+                // it before but it fell out of the top N and is now
+                // coming back
+
+                if (groupMap.Count < topNGroups)
+                {
+
+                    // Still in startup transient: we have not
+                    // seen enough unique groups to start pruning them;
+                    // just keep collecting them
+
+                    // Add a new CollectedSearchGroup:
+                    CollectedSearchGroup<TGroupValue> sg = new CollectedSearchGroup<TGroupValue>();
+                    sg.groupValue = CopyDocGroupValue(groupValue, default(TGroupValue));
+                    sg.ComparatorSlot = groupMap.Count;
+                    sg.TopDoc = docBase + doc;
+                    foreach (FieldComparator fc in comparators)
+                    {
+                        fc.Copy(sg.ComparatorSlot, doc);
+                    }
+                    groupMap[sg.groupValue] = sg;
+
+                    if (groupMap.Count == topNGroups)
+                    {
+                        // End of startup transient: we now have max
+                        // number of groups; from here on we will drop
+                        // bottom group when we insert new one:
+                        BuildSortedSet();
+                    }
+
+                    return;
+                }
+
+                // We already tested that the document is competitive, so replace
+                // the bottom group with this new group.
+                //CollectedSearchGroup<TGroupValue> bottomGroup = orderedGroups.PollLast();
+                CollectedSearchGroup<TGroupValue> bottomGroup;
+                lock (orderedGroups)
+                {
+                    bottomGroup = orderedGroups.Last();
+                    orderedGroups.Remove(bottomGroup);
+                }
+                Debug.Assert(orderedGroups.Count == topNGroups - 1);
+
+                groupMap.Remove(bottomGroup.groupValue);
+
+                // reuse the removed CollectedSearchGroup
+                bottomGroup.groupValue = CopyDocGroupValue(groupValue, bottomGroup.groupValue);
+                bottomGroup.TopDoc = docBase + doc;
+
+                foreach (FieldComparator fc in comparators)
+                {
+                    fc.Copy(bottomGroup.ComparatorSlot, doc);
+                }
+
+                groupMap[bottomGroup.groupValue] = bottomGroup;
+                orderedGroups.Add(bottomGroup);
+                Debug.Assert(orderedGroups.Count == topNGroups);
+
+                int lastComparatorSlot = orderedGroups.Last().ComparatorSlot;
+                foreach (FieldComparator fc in comparators)
+                {
+                    fc.Bottom = lastComparatorSlot;
+                }
+
+                return;
+            }
+
+            // Update existing group:
+            for (int compIDX = 0; ; compIDX++)
+            {
+                FieldComparator fc = comparators[compIDX];
+                fc.Copy(spareSlot, doc);
+
+                int c = reversed[compIDX] * fc.Compare(group.ComparatorSlot, spareSlot);
+                if (c < 0)
+                {
+                    // Definitely not competitive.
+                    return;
+                }
+                else if (c > 0)
+                {
+                    // Definitely competitive; set remaining comparators:
+                    for (int compIDX2 = compIDX + 1; compIDX2 < comparators.Length; compIDX2++)
+                    {
+                        comparators[compIDX2].Copy(spareSlot, doc);
+                    }
+                    break;
+                }
+                else if (compIDX == compIDXEnd)
+                {
+                    // Here c=0. If we're at the last comparator, this doc is not
+                    // competitive, since docs are visited in doc Id order, which means
+                    // this doc cannot compete with any other document in the queue.
+                    return;
+                }
+            }
+
+            // Remove before updating the group since lookup is done via comparators
+            // TODO: optimize this
+
+            CollectedSearchGroup<TGroupValue> prevLast;
+            if (orderedGroups != null)
+            {
+                lock (orderedGroups)
+                {
+                    prevLast = orderedGroups.Last();
+                    orderedGroups.Remove(group);
+                }
+                Debug.Assert(orderedGroups.Count == topNGroups - 1);
+            }
+            else
+            {
+                prevLast = null;
+            }
+
+            group.TopDoc = docBase + doc;
+
+            // Swap slots
+            int tmp = spareSlot;
+            spareSlot = group.ComparatorSlot;
+            group.ComparatorSlot = tmp;
+
+            // Re-add the changed group
+            if (orderedGroups != null)
+            {
+                orderedGroups.Add(group);
+                Debug.Assert(orderedGroups.Count == topNGroups);
+                var newLast = orderedGroups.Last();
+                // If we changed the value of the last group, or changed which group was last, then update bottom:
+                if (group == newLast || prevLast != newLast)
+                {
+                    foreach (FieldComparator fc in comparators)
+                    {
+                        fc.Bottom = newLast.ComparatorSlot;
+                    }
+                }
+            }
+        }
+
+        private class BuildSortedSetComparer : IComparer<ICollectedSearchGroup>
+        {
+            private readonly AbstractFirstPassGroupingCollector<TGroupValue> outerInstance;
+            public BuildSortedSetComparer(AbstractFirstPassGroupingCollector<TGroupValue> outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+            public int Compare(ICollectedSearchGroup o1, ICollectedSearchGroup o2)
+            {
+                for (int compIDX = 0; ; compIDX++)
+                {
+                    FieldComparator fc = outerInstance.comparators[compIDX];
+                    int c = outerInstance.reversed[compIDX] * fc.Compare(o1.ComparatorSlot, o2.ComparatorSlot);
+                    if (c != 0)
+                    {
+                        return c;
+                    }
+                    else if (compIDX == outerInstance.compIDXEnd)
+                    {
+                        return o1.TopDoc - o2.TopDoc;
+                    }
+                }
+            }
+        }
+        private void BuildSortedSet()
+        {
+            var comparator = new BuildSortedSetComparer(this);
+            //        var comparator = new Comparator<CollectedSearchGroup<?>>() {
+            //      @Override
+            //      public int compare(CollectedSearchGroup<?> o1, CollectedSearchGroup<?> o2)
+            //{
+            //    for (int compIDX = 0; ; compIDX++)
+            //    {
+            //        FieldComparator <?> fc = comparators[compIDX];
+            //        final int c = reversed[compIDX] * fc.compare(o1.comparatorSlot, o2.comparatorSlot);
+            //        if (c != 0)
+            //        {
+            //            return c;
+            //        }
+            //        else if (compIDX == compIDXEnd)
+            //        {
+            //            return o1.topDoc - o2.topDoc;
+            //        }
+            //    }
+            //}
+            //    };
+
+            orderedGroups = new SortedSet<CollectedSearchGroup<TGroupValue>>(comparator);
+            orderedGroups.UnionWith(groupMap.Values);
+            Debug.Assert(orderedGroups.Count > 0);
+
+            foreach (FieldComparator fc in comparators)
+            {
+                fc.Bottom = orderedGroups.Last().ComparatorSlot;
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return false;
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                docBase = value.DocBase;
+                for (int i = 0; i < comparators.Length; i++)
+                {
+                    comparators[i] = comparators[i].SetNextReader(value);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Returns the group value for the specified doc.
+        /// </summary>
+        /// <param name="doc">The specified doc</param>
+        /// <returns>the group value for the specified doc</returns>
+        protected abstract TGroupValue GetDocGroupValue(int doc);
+
+        /// <summary>
+        /// Returns a copy of the specified group value by creating a new instance and copying the value from the specified
+        /// groupValue in the new instance. Or optionally the reuse argument can be used to copy the group value in.
+        /// </summary>
+        /// <param name="groupValue">The group value to copy</param>
+        /// <param name="reuse">Optionally a reuse instance to prevent a new instance creation</param>
+        /// <returns>a copy of the specified group value</returns>
+        protected abstract TGroupValue CopyDocGroupValue(TGroupValue groupValue, TGroupValue reuse);
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
new file mode 100644
index 0000000..1cc4574
--- /dev/null
+++ b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
@@ -0,0 +1,375 @@
+\ufeffusing Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// Base class for computing grouped facets.
+    /// @lucene.experimental
+    /// </summary>
+    public abstract class AbstractGroupFacetCollector : Collector
+    {
+        protected readonly string groupField;
+        protected readonly string facetField;
+        protected readonly BytesRef facetPrefix;
+        protected readonly IList<AbstractSegmentResult> segmentResults;
+
+        protected int[] segmentFacetCounts;
+        protected int segmentTotalCount;
+        protected int startFacetOrd;
+        protected int endFacetOrd;
+
+        protected AbstractGroupFacetCollector(string groupField, string facetField, BytesRef facetPrefix)
+        {
+            this.groupField = groupField;
+            this.facetField = facetField;
+            this.facetPrefix = facetPrefix;
+            segmentResults = new List<AbstractSegmentResult>();
+        }
+
+        /**
+         * Returns grouped facet results that were computed over zero or more segments.
+         * Grouped facet counts are merged from zero or more segment results.
+         *
+         * @param size The total number of facets to include. This is typically offset + limit
+         * @param minCount The minimum count a facet entry should have to be included in the grouped facet result
+         * @param orderByCount Whether to sort the facet entries by facet entry count. If <code>false</code> then the facets
+         *                     are sorted lexicographically in ascending order.
+         * @return grouped facet results
+         * @throws IOException If I/O related errors occur during merging segment grouped facet counts.
+         */
+        public GroupedFacetResult MergeSegmentResults(int size, int minCount, bool orderByCount)
+        {
+            if (segmentFacetCounts != null)
+            {
+                segmentResults.Add(CreateSegmentResult());
+                segmentFacetCounts = null; // reset
+            }
+
+            int totalCount = 0;
+            int missingCount = 0;
+            SegmentResultPriorityQueue segments = new SegmentResultPriorityQueue(segmentResults.Count);
+            foreach (AbstractSegmentResult segmentResult in segmentResults)
+            {
+                missingCount += segmentResult.missing;
+                if (segmentResult.mergePos >= segmentResult.maxTermPos)
+                {
+                    continue;
+                }
+                totalCount += segmentResult.total;
+                segments.Add(segmentResult);
+            }
+
+            GroupedFacetResult facetResult = new GroupedFacetResult(size, minCount, orderByCount, totalCount, missingCount);
+            while (segments.Size() > 0)
+            {
+                AbstractSegmentResult segmentResult = segments.Top();
+                BytesRef currentFacetValue = BytesRef.DeepCopyOf(segmentResult.mergeTerm);
+                int count = 0;
+
+                do
+                {
+                    count += segmentResult.counts[segmentResult.mergePos++];
+                    if (segmentResult.mergePos < segmentResult.maxTermPos)
+                    {
+                        segmentResult.NextTerm();
+                        segmentResult = segments.UpdateTop();
+                    }
+                    else
+                    {
+                        segments.Pop();
+                        segmentResult = segments.Top();
+                        if (segmentResult == null)
+                        {
+                            break;
+                        }
+                    }
+                } while (currentFacetValue.Equals(segmentResult.mergeTerm));
+                facetResult.AddFacetCount(currentFacetValue, count);
+            }
+            return facetResult;
+        }
+
+        protected abstract AbstractSegmentResult CreateSegmentResult();
+
+        public override Scorer Scorer
+        {
+            set
+            {
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return true;
+        }
+
+        private class OrderByCountAndValueComparer : IComparer<FacetEntry>
+        {
+            public int Compare(FacetEntry a, FacetEntry b)
+            {
+                int cmp = b.Count - a.Count; // Highest count first!
+                if (cmp != 0)
+                {
+                    return cmp;
+                }
+                return a.Value.CompareTo(b.Value);
+            }
+        }
+
+        private class OrderByValueComparer : IComparer<FacetEntry>
+        {
+            public int Compare(FacetEntry a, FacetEntry b)
+            {
+                return a.Value.CompareTo(b.Value);
+            }
+        }
+
+        /**
+         * The grouped facet result. Containing grouped facet entries, total count and total missing count.
+         */
+        public class GroupedFacetResult
+        {
+            private readonly static IComparer<FacetEntry> orderByCountAndValue = new OrderByCountAndValueComparer();
+            //    private readonly static IComparer<FacetEntry> orderByCountAndValue = new Comparator<FacetEntry>() {
+
+            //      @Override
+            //      public override int Compare(FacetEntry a, FacetEntry b)
+            //    {
+            //        int cmp = b.count - a.count; // Highest count first!
+            //        if (cmp != 0)
+            //        {
+            //            return cmp;
+            //        }
+            //        return a.value.compareTo(b.value);
+            //    }
+
+            //};
+
+            private readonly static IComparer<FacetEntry> orderByValue = new OrderByValueComparer();
+
+            //            private readonly static IComparer<FacetEntry> orderByValue = new Comparator<FacetEntry>() {
+
+            //      @Override
+            //      public int compare(FacetEntry a, FacetEntry b)
+            //{
+            //    return a.value.compareTo(b.value);
+            //}
+
+            //    };
+
+            private readonly int maxSize;
+            private readonly SortedSet<FacetEntry> facetEntries;
+            private readonly int totalMissingCount;
+            private readonly int totalCount;
+
+            private int currentMin;
+
+            public GroupedFacetResult(int size, int minCount, bool orderByCount, int totalCount, int totalMissingCount)
+            {
+                this.facetEntries = new SortedSet<FacetEntry>(orderByCount ? orderByCountAndValue : orderByValue);
+                this.totalMissingCount = totalMissingCount;
+                this.totalCount = totalCount;
+                maxSize = size;
+                currentMin = minCount;
+            }
+
+            public virtual void AddFacetCount(BytesRef facetValue, int count)
+            {
+                if (count < currentMin)
+                {
+                    return;
+                }
+
+                FacetEntry facetEntry = new FacetEntry(facetValue, count);
+                if (facetEntries.Count == maxSize)
+                {
+                    // LUCENENET TODO: Add the C5.TreeSet to Support?
+                    // LUCENENET TODO: Finish implementation
+                    //if (facetEntries.Higher(facetEntry) == null)
+                    //{
+                    //    return;
+                    //}
+                    facetEntries.Remove(facetEntries.Last());
+                }
+                facetEntries.Add(facetEntry);
+
+                if (facetEntries.Count == maxSize)
+                {
+                    currentMin = facetEntries.Last().Count;
+                }
+            }
+
+            /**
+             * Returns a list of facet entries to be rendered based on the specified offset and limit.
+             * The facet entries are retrieved from the facet entries collected during merging.
+             *
+             * @param offset The offset in the collected facet entries during merging
+             * @param limit The number of facets to return starting from the offset.
+             * @return a list of facet entries to be rendered based on the specified offset and limit
+             */
+            public List<FacetEntry> GetFacetEntries(int offset, int limit)
+            {
+                List<FacetEntry> entries = new List<FacetEntry>();
+
+                int skipped = 0;
+                int included = 0;
+                foreach (FacetEntry facetEntry in facetEntries)
+                {
+                    if (skipped < offset)
+                    {
+                        skipped++;
+                        continue;
+                    }
+                    if (included++ >= limit)
+                    {
+                        break;
+                    }
+                    entries.Add(facetEntry);
+                }
+                return entries;
+            }
+
+            /**
+             * Returns the sum of all facet entries counts.
+             *
+             * @return the sum of all facet entries counts
+             */
+            public int TotalCount
+            {
+                get
+                {
+                    return totalCount;
+                }
+            }
+
+            /**
+             * Returns the number of groups that didn't have a facet value.
+             *
+             * @return the number of groups that didn't have a facet value
+             */
+            public int TotalMissingCount
+            {
+                get
+                {
+                    return totalMissingCount;
+                }
+            }
+        }
+
+        /**
+         * Represents a facet entry with a value and a count.
+         */
+        public class FacetEntry
+        {
+
+            private readonly BytesRef value;
+            private readonly int count;
+
+            public FacetEntry(BytesRef value, int count)
+            {
+                this.value = value;
+                this.count = count;
+            }
+
+            public override bool Equals(object o)
+            {
+                if (this == o) return true;
+                if (o == null || GetType() != o.GetType()) return false;
+
+                FacetEntry that = (FacetEntry)o;
+
+                if (count != that.count) return false;
+                if (!value.Equals(that.value)) return false;
+
+                return true;
+            }
+
+            public override int GetHashCode()
+            {
+                int result = value.GetHashCode();
+                result = 31 * result + count;
+                return result;
+            }
+
+            public override string ToString()
+            {
+                return "FacetEntry{" +
+                    "value=" + value.Utf8ToString() +
+                    ", count=" + count +
+                    '}';
+            }
+
+            /**
+             * @return The value of this facet entry
+             */
+            public BytesRef Value
+            {
+                get
+                {
+                    return value;
+                }
+            }
+
+            /**
+             * @return The count (number of groups) of this facet entry.
+             */
+            public int Count
+            {
+                get
+                {
+                    return count;
+                }
+            }
+        }
+
+        /**
+         * Contains the local grouped segment counts for a particular segment.
+         * Each <code>SegmentResult</code> must be added together.
+         */
+        protected internal abstract class AbstractSegmentResult
+        {
+            protected internal readonly int[] counts;
+            protected internal readonly int total;
+            protected internal readonly int missing;
+            protected internal readonly int maxTermPos;
+
+            protected internal BytesRef mergeTerm;
+            protected internal int mergePos;
+
+            protected AbstractSegmentResult(int[] counts, int total, int missing, int maxTermPos)
+            {
+                this.counts = counts;
+                this.total = total;
+                this.missing = missing;
+                this.maxTermPos = maxTermPos;
+            }
+
+            /**
+             * Go to next term in this <code>SegmentResult</code> in order to retrieve the grouped facet counts.
+             *
+             * @throws IOException If I/O related errors occur
+             */
+            protected internal abstract void NextTerm();
+
+        }
+
+        private class SegmentResultPriorityQueue : PriorityQueue<AbstractSegmentResult>
+        {
+            internal SegmentResultPriorityQueue(int maxSize)
+                : base(maxSize)
+            {
+            }
+
+            public override bool LessThan(AbstractSegmentResult a, AbstractSegmentResult b)
+            {
+                return a.mergeTerm.CompareTo(b.mergeTerm) < 0;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
new file mode 100644
index 0000000..580617c
--- /dev/null
+++ b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
@@ -0,0 +1,170 @@
+\ufeffusing Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Lucene.Net.Index;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// SecondPassGroupingCollector is the second of two passes
+    /// necessary to collect grouped docs.  This pass gathers the
+    /// top N documents per top group computed from the
+    /// first pass. Concrete subclasses define what a group is and how it
+    /// is internally collected.
+    /// <para>
+    /// See {@link org.apache.lucene.search.grouping} for more
+    /// details including a full code example.
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public abstract class AbstractSecondPassGroupingCollector<TGroupValue> : Collector
+    {
+        protected readonly IDictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>> groupMap;
+        private readonly int maxDocsPerGroup;
+        protected AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>[] groupDocs;
+        private readonly ICollection<SearchGroup<TGroupValue>> groups;
+        private readonly Sort withinGroupSort;
+        private readonly Sort groupSort;
+
+        private int totalHitCount;
+        private int totalGroupedHitCount;
+
+        public AbstractSecondPassGroupingCollector(ICollection<SearchGroup<TGroupValue>> groups, Sort groupSort, Sort withinGroupSort,
+                                                   int maxDocsPerGroup, bool getScores, bool getMaxScores, bool fillSortFields)
+        {
+
+            //System.out.println("SP init");
+            if (groups.Count == 0)
+            {
+                throw new ArgumentException("no groups to collect (groups.size() is 0)");
+            }
+
+            this.groupSort = groupSort;
+            this.withinGroupSort = withinGroupSort;
+            this.groups = groups;
+            this.maxDocsPerGroup = maxDocsPerGroup;
+            groupMap = new Dictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>>(groups.Count);
+
+            foreach (SearchGroup<TGroupValue> group in groups)
+            {
+                //System.out.println("  prep group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
+                //TopDocsCollector collector;
+                ITopDocsCollector collector;
+                if (withinGroupSort == null)
+                {
+                    // Sort by score
+                    collector = TopScoreDocCollector.Create(maxDocsPerGroup, true);
+                }
+                else
+                {
+                    // Sort by fields
+                    collector = TopFieldCollector.Create(withinGroupSort, maxDocsPerGroup, fillSortFields, getScores, getMaxScores, true);
+                }
+                groupMap[group.groupValue] = new AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>(group.groupValue, collector);
+            }
+        }
+
+        public override Scorer Scorer
+        {
+            set
+            {
+                foreach (AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> group in groupMap.Values)
+                {
+                    group.collector.Scorer = value;
+                }
+            }
+        }
+
+        public override void Collect(int doc)
+        {
+            totalHitCount++;
+            AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> group = RetrieveGroup(doc);
+            if (group != null)
+            {
+                totalGroupedHitCount++;
+                group.collector.Collect(doc);
+            }
+        }
+
+        /**
+         * Returns the group the specified doc belongs to or <code>null</code> if no group could be retrieved.
+         *
+         * @param doc The specified doc
+         * @return the group the specified doc belongs to or <code>null</code> if no group could be retrieved
+         * @throws IOException If an I/O related error occurred
+         */
+        protected abstract AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> RetrieveGroup(int doc);
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                //System.out.println("SP.setNextReader");
+                foreach (AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> group in groupMap.Values)
+                {
+                    group.collector.NextReader = value;
+                }
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return false;
+        }
+
+        public TopGroups<TGroupValue> GetTopGroups(int withinGroupOffset)
+        {
+            GroupDocs<TGroupValue>[] groupDocsResult = new GroupDocs<TGroupValue>[groups.Count];
+
+            int groupIDX = 0;
+            float maxScore = float.MinValue;
+            foreach (var group in groups)
+            {
+                AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> groupDocs = groupMap.ContainsKey(group.groupValue) ? groupMap[group.groupValue] : null;
+                TopDocs topDocs = groupDocs.collector.TopDocs(withinGroupOffset, maxDocsPerGroup);
+                groupDocsResult[groupIDX++] = new GroupDocs<TGroupValue>(float.NaN,
+                                                                              topDocs.MaxScore,
+                                                                              topDocs.TotalHits,
+                                                                              topDocs.ScoreDocs,
+                                                                              groupDocs.groupValue,
+                                                                              group.sortValues);
+                maxScore = Math.Max(maxScore, topDocs.MaxScore);
+            }
+
+            return new TopGroups<TGroupValue>(groupSort.GetSort(),
+                                                   withinGroupSort == null ? null : withinGroupSort.GetSort(),
+                                                   totalHitCount, totalGroupedHitCount, groupDocsResult,
+                                                   maxScore);
+        }
+
+
+        
+    }
+
+    public class AbstractSecondPassGroupingCollector
+    {
+        /// <summary>
+        /// Don't allow creation
+        /// </summary>
+        private AbstractSecondPassGroupingCollector() { }
+
+        // TODO: merge with SearchGroup or not?
+        // ad: don't need to build a new hashmap
+        // disad: blows up the size of SearchGroup if we need many of them, and couples implementations
+        public class SearchGroupDocs<TGroupValue>
+        {
+            public readonly TGroupValue groupValue;
+            //public readonly TopDocsCollector<?> collector;
+            public readonly ITopDocsCollector collector;
+            public SearchGroupDocs(TGroupValue groupValue, ITopDocsCollector /*TopDocsCollector<?>*/ collector)
+            {
+                this.groupValue = groupValue;
+                this.collector = collector;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
new file mode 100644
index 0000000..2a82993
--- /dev/null
+++ b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
@@ -0,0 +1,601 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    // TODO: this sentence is too long for the class summary.
+    /// <summary>
+    /// BlockGroupingCollector performs grouping with a
+    /// single pass collector, as long as you are grouping by a
+    /// doc block field, ie all documents sharing a given group
+    /// value were indexed as a doc block using the atomic
+    /// <see cref="IndexWriter.AddDocuments(IEnumerable{IEnumerable{IndexableField}}, Analysis.Analyzer)"/> or
+    /// <see cref="IndexWriter.UpdateDocuments(Term, IEnumerable{IEnumerable{IndexableField}}, Analysis.Analyzer)"/>
+    /// API.
+    /// 
+    /// <para>
+    /// This results in faster performance (~25% faster QPS)
+    /// than the two-pass grouping collectors, with the tradeoff
+    /// being that the documents in each group must always be
+    /// indexed as a block.  This collector also fills in
+    /// TopGroups.totalGroupCount without requiring the separate
+    /// <see cref="Terms.TermAllGroupsCollector"/>. However, this collector does
+    /// not fill in the groupValue of each group; this field
+    /// will always be null.
+    /// </para>
+    /// <para>
+    /// <c>NOTE</c>: this collector makes no effort to verify
+    /// the docs were in fact indexed as a block, so it's up to
+    /// you to ensure this was the case.
+    /// </para>
+    /// <para>
+    /// See {@link org.apache.lucene.search.grouping} for more
+    /// details including a full code example.
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
+    public class BlockGroupingCollector : Collector
+    {
+        private int[] pendingSubDocs;
+        private float[] pendingSubScores;
+        private int subDocUpto;
+
+        private readonly Sort groupSort;
+        private readonly int topNGroups;
+        private readonly Filter lastDocPerGroup;
+
+        // TODO: specialize into 2 classes, static "create" method:
+        private readonly bool needsScores;
+
+        private readonly FieldComparator[] comparators;
+        private readonly int[] reversed;
+        private readonly int compIDXEnd;
+        private int bottomSlot;
+        private bool queueFull;
+        private AtomicReaderContext currentReaderContext;
+
+        private int topGroupDoc;
+        private int totalHitCount;
+        private int totalGroupCount;
+        private int docBase;
+        private int groupEndDocID;
+        private DocIdSetIterator lastDocPerGroupBits;
+        private Scorer scorer;
+        private readonly GroupQueue groupQueue;
+        private bool groupCompetes;
+
+        private sealed class FakeScorer : Scorer
+        {
+            internal float score;
+            internal int doc;
+
+            public FakeScorer()
+                    : base(null)
+            {
+            }
+
+            public override float Score()
+            {
+                return score;
+            }
+
+            public override int Freq()
+            {
+                throw new InvalidOperationException(); // TODO: wtf does this class do?
+            }
+
+            public override int DocID()
+            {
+                return doc;
+            }
+
+            public override int Advance(int target)
+            {
+                throw new InvalidOperationException();
+            }
+
+            public override int NextDoc()
+            {
+                throw new InvalidOperationException();
+            }
+
+            public override long Cost()
+            {
+                return 1;
+            }
+
+            public override Weight Weight
+            {
+                get
+                {
+                    throw new InvalidOperationException();
+                }
+            }
+
+
+            public override ICollection<ChildScorer> Children
+            {
+                get
+                {
+                    throw new InvalidOperationException();
+                }
+            }
+        }
+
+        private sealed class OneGroup
+        {
+            internal AtomicReaderContext readerContext;
+            //internal int groupOrd;
+            internal int topGroupDoc;
+            internal int[] docs;
+            internal float[] scores;
+            internal int count;
+            internal int comparatorSlot;
+        }
+
+        // Sorts by groupSort.  Not static -- uses comparators, reversed
+        private sealed class GroupQueue : PriorityQueue<OneGroup>
+        {
+
+            private readonly BlockGroupingCollector outerInstance;
+            public GroupQueue(BlockGroupingCollector outerInstance, int size)
+                        : base(size)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public override bool LessThan(OneGroup group1, OneGroup group2)
+            {
+
+                //System.out.println("    ltcheck");
+                Debug.Assert(group1 != group2);
+                Debug.Assert(group1.comparatorSlot != group2.comparatorSlot);
+
+                int numComparators = outerInstance.comparators.Length;
+                for (int compIDX = 0; compIDX < numComparators; compIDX++)
+                {
+                    int c = outerInstance.reversed[compIDX] * outerInstance.comparators[compIDX].Compare(group1.comparatorSlot, group2.comparatorSlot);
+                    if (c != 0)
+                    {
+                        // Short circuit
+                        return c > 0;
+                    }
+                }
+
+                // Break ties by docID; lower docID is always sorted first
+                return group1.topGroupDoc > group2.topGroupDoc;
+            }
+        }
+
+        // Called when we transition to another group; if the
+        // group is competitive we insert into the group queue
+        private void ProcessGroup()
+        {
+            totalGroupCount++;
+            //System.out.println("    processGroup ord=" + lastGroupOrd + " competes=" + groupCompetes + " count=" + subDocUpto + " groupDoc=" + topGroupDoc);
+            if (groupCompetes)
+            {
+                if (!queueFull)
+                {
+                    // Startup transient: always add a new OneGroup
+                    OneGroup og = new OneGroup();
+                    og.count = subDocUpto;
+                    og.topGroupDoc = docBase + topGroupDoc;
+                    og.docs = pendingSubDocs;
+                    pendingSubDocs = new int[10];
+                    if (needsScores)
+                    {
+                        og.scores = pendingSubScores;
+                        pendingSubScores = new float[10];
+                    }
+                    og.readerContext = currentReaderContext;
+                    //og.groupOrd = lastGroupOrd;
+                    og.comparatorSlot = bottomSlot;
+                    OneGroup bottomGroup = groupQueue.Add(og);
+                    //System.out.println("      ADD group=" + getGroupString(lastGroupOrd) + " newBottom=" + getGroupString(bottomGroup.groupOrd));
+                    queueFull = groupQueue.Size() == topNGroups;
+                    if (queueFull)
+                    {
+                        // Queue just became full; now set the real bottom
+                        // in the comparators:
+                        bottomSlot = bottomGroup.comparatorSlot;
+                        //System.out.println("    set bottom=" + bottomSlot);
+                        for (int i = 0; i < comparators.Length; i++)
+                        {
+                            comparators[i].Bottom = bottomSlot;
+                        }
+                        //System.out.println("     QUEUE FULL");
+                    }
+                    else
+                    {
+                        // Queue not full yet -- just advance bottomSlot:
+                        bottomSlot = groupQueue.Size();
+                    }
+                }
+                else
+                {
+                    // Replace bottom element in PQ and then updateTop
+                    OneGroup og = groupQueue.Top();
+                    Debug.Assert(og != null);
+                    og.count = subDocUpto;
+                    og.topGroupDoc = docBase + topGroupDoc;
+                    // Swap pending docs
+                    int[] savDocs = og.docs;
+                    og.docs = pendingSubDocs;
+                    pendingSubDocs = savDocs;
+                    if (needsScores)
+                    {
+                        // Swap pending scores
+                        float[] savScores = og.scores;
+                        og.scores = pendingSubScores;
+                        pendingSubScores = savScores;
+                    }
+                    og.readerContext = currentReaderContext;
+                    //og.groupOrd = lastGroupOrd;
+                    bottomSlot = groupQueue.UpdateTop().comparatorSlot;
+
+                    //System.out.println("    set bottom=" + bottomSlot);
+                    for (int i = 0; i < comparators.Length; i++)
+                    {
+                        comparators[i].Bottom = bottomSlot;
+                    }
+                }
+            }
+            subDocUpto = 0;
+        }
+
+        /**
+         * Create the single pass collector.
+         *
+         *  @param groupSort The {@link Sort} used to sort the
+         *    groups.  The top sorted document within each group
+         *    according to groupSort, determines how that group
+         *    sorts against other groups.  This must be non-null,
+         *    ie, if you want to groupSort by relevance use
+         *    Sort.RELEVANCE.
+         *  @param topNGroups How many top groups to keep.
+         *  @param needsScores true if the collected documents
+         *    require scores, either because relevance is included
+         *    in the withinGroupSort or because you plan to pass true
+         *    for either getSscores or getMaxScores to {@link
+         *    #getTopGroups}
+         *  @param lastDocPerGroup a {@link Filter} that marks the
+         *    last document in each group.
+         */
+        public BlockGroupingCollector(Sort groupSort, int topNGroups, bool needsScores, Filter lastDocPerGroup)
+        {
+
+            if (topNGroups < 1)
+            {
+                throw new ArgumentException("topNGroups must be >= 1 (got " + topNGroups + ")");
+            }
+
+            groupQueue = new GroupQueue(this, topNGroups);
+            pendingSubDocs = new int[10];
+            if (needsScores)
+            {
+                pendingSubScores = new float[10];
+            }
+
+            this.needsScores = needsScores;
+            this.lastDocPerGroup = lastDocPerGroup;
+            // TODO: allow null groupSort to mean "by relevance",
+            // and specialize it?
+            this.groupSort = groupSort;
+
+            this.topNGroups = topNGroups;
+
+            SortField[] sortFields = groupSort.GetSort();
+            comparators = new FieldComparator[sortFields.Length];
+            compIDXEnd = comparators.Length - 1;
+            reversed = new int[sortFields.Length];
+            for (int i = 0; i < sortFields.Length; i++)
+            {
+                SortField sortField = sortFields[i];
+                comparators[i] = sortField.GetComparator(topNGroups, i);
+                reversed[i] = sortField.Reverse ? -1 : 1;
+            }
+        }
+
+        // TODO: maybe allow no sort on retrieving groups?  app
+        // may want to simply process docs in the group itself?
+        // typically they will be presented as a "single" result
+        // in the UI?
+
+        /** Returns the grouped results.  Returns null if the
+         *  number of groups collected is <= groupOffset.
+         *
+         *  <p><b>NOTE</b>: This collector is unable to compute
+         *  the groupValue per group so it will always be null.
+         *  This is normally not a problem, as you can obtain the
+         *  value just like you obtain other values for each
+         *  matching document (eg, via stored fields, via
+         *  FieldCache, etc.)
+         *
+         *  @param withinGroupSort The {@link Sort} used to sort
+         *    documents within each group.  Passing null is
+         *    allowed, to sort by relevance.
+         *  @param groupOffset Which group to start from
+         *  @param withinGroupOffset Which document to start from
+         *    within each group
+         *  @param maxDocsPerGroup How many top documents to keep
+         *     within each group.
+         *  @param fillSortFields If true then the Comparable
+         *     values for the sort fields will be set
+         */
+        public TopGroups<T> GetTopGroups<T>(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
+        {
+
+            //if (queueFull) {
+            //System.out.println("getTopGroups groupOffset=" + groupOffset + " topNGroups=" + topNGroups);
+            //}
+            if (subDocUpto != 0)
+            {
+                ProcessGroup();
+            }
+            if (groupOffset >= groupQueue.Size())
+            {
+                return null;
+            }
+            int totalGroupedHitCount = 0;
+
+            FakeScorer fakeScorer = new FakeScorer();
+
+            float maxScore = float.MinValue;
+
+            GroupDocs<T>[] groups = new GroupDocs<T>[groupQueue.Size() - groupOffset];
+            for (int downTo = groupQueue.Size() - groupOffset - 1; downTo >= 0; downTo--)
+            {
+                OneGroup og = groupQueue.Pop();
+
+                // At this point we hold all docs w/ in each group,
+                // unsorted; we now sort them:
+                ITopDocsCollector collector;
+                if (withinGroupSort == null)
+                {
+                    // Sort by score
+                    if (!needsScores)
+                    {
+                        throw new ArgumentException("cannot sort by relevance within group: needsScores=false");
+                    }
+                    collector = TopScoreDocCollector.Create(maxDocsPerGroup, true);
+                }
+                else
+                {
+                    // Sort by fields
+                    collector = TopFieldCollector.Create(withinGroupSort, maxDocsPerGroup, fillSortFields, needsScores, needsScores, true);
+                }
+
+                collector.Scorer = fakeScorer;
+                collector.NextReader = og.readerContext;
+                for (int docIDX = 0; docIDX < og.count; docIDX++)
+                {
+                    int doc = og.docs[docIDX];
+                    fakeScorer.doc = doc;
+                    if (needsScores)
+                    {
+                        fakeScorer.score = og.scores[docIDX];
+                    }
+                    collector.Collect(doc);
+                }
+                totalGroupedHitCount += og.count;
+
+                object[] groupSortValues;
+
+                if (fillSortFields)
+                {
+                    groupSortValues = new IComparable[comparators.Length];
+                    for (int sortFieldIDX = 0; sortFieldIDX < comparators.Length; sortFieldIDX++)
+                    {
+                        groupSortValues[sortFieldIDX] = comparators[sortFieldIDX].Value(og.comparatorSlot);
+                    }
+                }
+                else
+                {
+                    groupSortValues = null;
+                }
+
+                TopDocs topDocs = collector.TopDocs(withinGroupOffset, maxDocsPerGroup);
+
+                // TODO: we could aggregate scores across children
+                // by Sum/Avg instead of passing NaN:
+                groups[downTo] = new GroupDocs<T>(float.NaN,
+                                                       topDocs.MaxScore,
+                                                       og.count,
+                                                       topDocs.ScoreDocs,
+                                                       default(T),
+                                                       groupSortValues);
+                maxScore = Math.Max(maxScore, topDocs.MaxScore);
+            }
+
+            /*
+            while (groupQueue.size() != 0) {
+              final OneGroup og = groupQueue.pop();
+              //System.out.println("  leftover: og ord=" + og.groupOrd + " count=" + og.count);
+              totalGroupedHitCount += og.count;
+            }
+            */
+
+            return new TopGroups<T>(new TopGroups<T>(groupSort.GetSort(),
+                                               withinGroupSort == null ? null : withinGroupSort.GetSort(),
+                                               totalHitCount, totalGroupedHitCount, groups, maxScore),
+                                 totalGroupCount);
+        }
+
+        public override Scorer Scorer
+        {
+            set
+            {
+                this.scorer = value;
+                foreach (FieldComparator comparator in comparators)
+                {
+                    comparator.Scorer = value;
+                }
+            }
+        }
+
+        public override void Collect(int doc)
+        {
+
+            // System.out.println("C " + doc);
+
+            if (doc > groupEndDocID)
+            {
+                // Group changed
+                if (subDocUpto != 0)
+                {
+                    ProcessGroup();
+                }
+                groupEndDocID = lastDocPerGroupBits.Advance(doc);
+                //System.out.println("  adv " + groupEndDocID + " " + lastDocPerGroupBits);
+                subDocUpto = 0;
+                groupCompetes = !queueFull;
+            }
+
+            totalHitCount++;
+
+            // Always cache doc/score within this group:
+            if (subDocUpto == pendingSubDocs.Length)
+            {
+                pendingSubDocs = ArrayUtil.Grow(pendingSubDocs);
+            }
+            pendingSubDocs[subDocUpto] = doc;
+            if (needsScores)
+            {
+                if (subDocUpto == pendingSubScores.Length)
+                {
+                    pendingSubScores = ArrayUtil.Grow(pendingSubScores);
+                }
+                pendingSubScores[subDocUpto] = scorer.Score();
+            }
+            subDocUpto++;
+
+            if (groupCompetes)
+            {
+                if (subDocUpto == 1)
+                {
+                    Debug.Assert(!queueFull);
+
+                    //System.out.println("    init copy to bottomSlot=" + bottomSlot);
+                    foreach (FieldComparator fc in comparators)
+                    {
+                        fc.Copy(bottomSlot, doc);
+                        fc.Bottom = bottomSlot;
+                    }
+                    topGroupDoc = doc;
+                }
+                else
+                {
+                    // Compare to bottomSlot
+                    for (int compIDX = 0; ; compIDX++)
+                    {
+                        int c = reversed[compIDX] * comparators[compIDX].CompareBottom(doc);
+                        if (c < 0)
+                        {
+                            // Definitely not competitive -- done
+                            return;
+                        }
+                        else if (c > 0)
+                        {
+                            // Definitely competitive.
+                            break;
+                        }
+                        else if (compIDX == compIDXEnd)
+                        {
+                            // Ties with bottom, except we know this docID is
+                            // > docID in the queue (docs are visited in
+                            // order), so not competitive:
+                            return;
+                        }
+                    }
+
+                    //System.out.println("       best w/in group!");
+
+                    foreach (FieldComparator fc in comparators)
+                    {
+                        fc.Copy(bottomSlot, doc);
+                        // Necessary because some comparators cache
+                        // details of bottom slot; this forces them to
+                        // re-cache:
+                        fc.Bottom = bottomSlot;
+                    }
+                    topGroupDoc = doc;
+                }
+            }
+            else
+            {
+                // We're not sure this group will make it into the
+                // queue yet
+                for (int compIDX = 0; ; compIDX++)
+                {
+                    int c = reversed[compIDX] * comparators[compIDX].CompareBottom(doc);
+                    if (c < 0)
+                    {
+                        // Definitely not competitive -- done
+                        //System.out.println("    doc doesn't compete w/ top groups");
+                        return;
+                    }
+                    else if (c > 0)
+                    {
+                        // Definitely competitive.
+                        break;
+                    }
+                    else if (compIDX == compIDXEnd)
+                    {
+                        // Ties with bottom, except we know this docID is
+                        // > docID in the queue (docs are visited in
+                        // order), so not competitive:
+                        //System.out.println("    doc doesn't compete w/ top groups");
+                        return;
+                    }
+                }
+                groupCompetes = true;
+                foreach (FieldComparator fc in comparators)
+                {
+                    fc.Copy(bottomSlot, doc);
+                    // Necessary because some comparators cache
+                    // details of bottom slot; this forces them to
+                    // re-cache:
+                    fc.Bottom = bottomSlot;
+                }
+                topGroupDoc = doc;
+                //System.out.println("        doc competes w/ top groups");
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return false;
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                if (subDocUpto != 0)
+                {
+                    ProcessGroup();
+                }
+                subDocUpto = 0;
+                docBase = value.DocBase;
+                //System.out.println("setNextReader base=" + docBase + " r=" + readerContext.reader);
+                lastDocPerGroupBits = lastDocPerGroup.GetDocIdSet(value, value.AtomicReader.LiveDocs).GetIterator();
+                groupEndDocID = -1;
+
+                currentReaderContext = value;
+                for (int i = 0; i < comparators.Length; i++)
+                {
+                    comparators[i] = comparators[i].SetNextReader(value);
+                }
+
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
new file mode 100644
index 0000000..9ed6cb8
--- /dev/null
+++ b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
@@ -0,0 +1,31 @@
+\ufeffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// Expert: representation of a group in {@link AbstractFirstPassGroupingCollector},
+    /// tracking the top doc and {@link FieldComparator} slot.
+    /// @lucene.internal
+    /// </summary>
+    /// <typeparam name="TGroupValue"></typeparam>
+    public class CollectedSearchGroup<TGroupValue> : SearchGroup<TGroupValue>, ICollectedSearchGroup
+    {
+        public int TopDoc { get; internal set; }
+        public int ComparatorSlot { get; internal set; }
+    }
+
+
+    /// <summary>
+    /// LUCENENET specific interface for passing/comparing the CollectedSearchGroup
+    /// without referencing its generic type
+    /// </summary>
+    public interface ICollectedSearchGroup
+    {
+        int TopDoc { get; }
+        int ComparatorSlot { get; }
+    }
+}


[25/58] [abbrv] lucenenet git commit: HACK: (3rd) Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context.

Posted by ni...@apache.org.
HACK: (3rd) Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context.


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

Branch: refs/heads/grouping
Commit: a209d7183138d3f2179b03113626ce5708f6e835
Parents: d67ed2b
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Tue Nov 8 02:19:34 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:23:40 2016 +0700

----------------------------------------------------------------------
 .../BaseCompressingDocValuesFormatTestCase.cs   |   3 +
 .../Index/BaseDocValuesFormatTestCase.cs        | 156 +++---
 .../Index/BaseIndexFileFormatTestCase.cs        |   2 +-
 .../Index/BasePostingsFormatTestCase.cs         |  14 +-
 .../Index/BaseStoredFieldsFormatTestCase.cs     |  22 +-
 .../Index/BaseTermVectorsFormatTestCase.cs      |  14 +-
 .../Util/BaseDocIdSetTestCase.cs                |  10 +-
 .../BlockTerms/TestFixedGapPostingsFormat.cs    |  63 +++
 .../Bloom/TestBloomPostingsFormat.cs            |  63 +++
 .../DiskDv/TestDiskDocValuesFormat.cs           | 526 ++++++++++++++++++
 .../IntBlock/TestFixedIntBlockPostingsFormat.cs |  63 +++
 .../TestVariableIntBlockPostingsFormat.cs       |  63 +++
 .../Memory/TestDirectDocValuesFormat.cs         | 501 ++++++++++++++++++
 .../Memory/TestDirectPostingsFormat.cs          |  63 +++
 .../Memory/TestFSTOrdPostingsFormat.cs          |  63 +++
 .../Memory/TestFSTOrdPulsing41PostingsFormat.cs |  63 +++
 .../Memory/TestFSTPostingsFormat.cs             |  63 +++
 .../Memory/TestFSTPulsing41PostingsFormat.cs    |  63 +++
 .../Memory/TestMemoryDocValuesFormat.cs         | 526 ++++++++++++++++++
 .../Memory/TestMemoryPostingsFormat.cs          |  62 +++
 .../Pulsing/TestPulsingPostingsFormat.cs        |  63 +++
 .../Sep/TestSepPostingsFormat.cs                |  62 +++
 .../SimpleText/TestSimpleTextDocValuesFormat.cs | 500 ++++++++++++++++++
 .../SimpleText/TestSimpleTextPostingsFormat.cs  |  63 +++
 .../TestSimpleTextStoredFieldsFormat.cs         |  88 ++++
 .../TestSimpleTextTermVectorsFormat.cs          |  66 +++
 .../Index/Sorter/IndexSortingTest.cs            |  56 ++
 .../Index/Sorter/SorterTestBase.cs              |  16 +-
 .../Index/Sorter/SortingAtomicReaderTest.cs     |  56 ++
 .../Classic/TestQueryParser.cs                  | 250 +++++++++
 .../Ext/TestExtendableQueryParser.cs            | 369 +++++++++++++
 .../Compressing/AbstractTestCompressionMode.cs  |  14 +-
 .../AbstractTestLZ4CompressionMode.cs           |   8 +-
 .../TestCompressingStoredFieldsFormat.cs        |  89 ++++
 .../TestCompressingTermVectorsFormat.cs         |  67 +++
 .../Compressing/TestFastCompressionMode.cs      |  81 +++
 .../Compressing/TestFastDecompressionMode.cs    |  81 +++
 .../Compressing/TestHighCompressionMode.cs      |  50 ++
 .../Lucene3x/TestLucene3xPostingsFormat.cs      |  63 +++
 .../Lucene3x/TestLucene3xStoredFieldsFormat.cs  |  84 +++
 .../Lucene3x/TestLucene3xTermVectorsFormat.cs   |  67 +++
 .../Lucene40/TestLucene40DocValuesFormat.cs     | 501 ++++++++++++++++++
 .../Lucene40/TestLucene40PostingsFormat.cs      |  63 +++
 .../Lucene40/TestLucene40StoredFieldsFormat.cs  |  89 ++++
 .../Lucene40/TestLucene40TermVectorsFormat.cs   |  67 +++
 .../Codecs/Lucene41/TestBlockPostingsFormat.cs  |  65 +++
 .../Lucene41/TestLucene41StoredFieldsFormat.cs  |  89 ++++
 .../Lucene42/TestLucene42DocValuesFormat.cs     | 526 ++++++++++++++++++
 .../Lucene45/TestLucene45DocValuesFormat.cs     | 527 +++++++++++++++++++
 .../Perfield/TestPerFieldDocValuesFormat.cs     | 501 ++++++++++++++++++
 .../Perfield/TestPerFieldPostingsFormat.cs      |  51 ++
 .../core/Index/TestDocValuesFormat.cs           | 503 ++++++++++++++++++
 .../core/Index/TestLogMergePolicy.cs            |  15 +
 .../core/Index/TestNumericDocValuesUpdates.cs   |   2 +-
 .../TestPersistentSnapshotDeletionPolicy.cs     |  50 ++
 .../core/Index/TestPostingsFormat.cs            |  50 ++
 .../core/Index/TestStoredFieldsFormat.cs        |  83 +++
 .../core/Index/TestTermVectorsFormat.cs         |  55 ++
 .../core/Index/TestTieredMergePolicy.cs         |  14 +
 .../core/Search/BaseTestRangeFilter.cs          |   2 +-
 .../Spans/TestSpanExplanationsOfNonMatches.cs   | 214 ++++++++
 .../TestComplexExplanationsOfNonMatches.cs      | 160 ++++++
 .../core/Search/TestExplanations.cs             |   2 +-
 .../core/Search/TestFieldCacheRangeFilter.cs    |  14 +
 .../core/Search/TestFieldCacheRewriteMethod.cs  |  17 +
 .../core/Search/TestMultiTermConstantScore.cs   |  14 +
 .../core/Search/TestSimpleExplanations.cs       |  19 +
 .../TestSimpleExplanationsOfNonMatches.cs       | 452 ++++++++++++++++
 .../core/Search/TestTermRangeFilter.cs          |  14 +
 .../core/Support/TestLinkedHashMap.cs           |  80 +++
 .../core/Support/TestLurchTable.cs              | 176 ++++++-
 .../core/Util/BaseSortTestCase.cs               |  18 +-
 .../core/Util/Packed/TestEliasFanoDocIdSet.cs   |  45 ++
 .../core/Util/TestDocIdBitSet.cs                |  46 ++
 .../core/Util/TestFixedBitSet.cs                |  45 ++
 .../core/Util/TestInPlaceMergeSorter.cs         |  64 +++
 .../core/Util/TestIntroSorter.cs                |  64 +++
 .../core/Util/TestOpenBitSet.cs                 |  44 ++
 .../core/Util/TestPForDeltaDocIdSet.cs          |  44 ++
 src/Lucene.Net.Tests/core/Util/TestTimSorter.cs |  64 +++
 .../core/Util/TestWAH8DocIdSet.cs               |  44 ++
 81 files changed, 9330 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
index d88ecb4..54d7fd5 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
@@ -45,6 +45,7 @@ namespace Lucene.Net.Index
             return size;
         }
 
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestUniqueValuesCompression()
         {
             Directory dir = new RAMDirectory();
@@ -85,6 +86,7 @@ namespace Lucene.Net.Index
             Assert.IsTrue(size2 < size1 + 8 * 20);
         }
 
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDateCompression()
         {
             Directory dir = new RAMDirectory();
@@ -115,6 +117,7 @@ namespace Lucene.Net.Index
             Assert.IsTrue(size2 < size1 + (PackedInts.BitsRequired(day) * 50) / 8);
         }
 
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSingleBigValueCompression()
         {
             Directory dir = new RAMDirectory();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
index ebc4c19..fa46ef8 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
@@ -84,7 +84,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestOneNumber()
         {
             Directory directory = NewDirectory();
@@ -119,7 +119,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestOneFloat()
         {
             Directory directory = NewDirectory();
@@ -154,7 +154,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoNumbers()
         {
             Directory directory = NewDirectory();
@@ -192,7 +192,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoBinaryValues()
         {
             Directory directory = NewDirectory();
@@ -233,7 +233,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoFieldsMixed()
         {
             Directory directory = NewDirectory();
@@ -273,7 +273,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestThreeFieldsMixed()
         {
             Directory directory = NewDirectory();
@@ -318,7 +318,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestThreeFieldsMixed2()
         {
             Directory directory = NewDirectory();
@@ -363,7 +363,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoDocumentsNumeric()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -392,7 +392,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoDocumentsMerged()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -436,7 +436,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBigNumericRange()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -465,7 +465,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBigNumericRange2()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -494,7 +494,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -534,7 +534,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBytesTwoDocumentsMerged()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -580,7 +580,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -620,7 +620,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedBytesTwoDocuments()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -652,7 +652,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedBytesThreeDocuments()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -691,7 +691,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedBytesTwoDocumentsMerged()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -742,7 +742,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedMergeAwayAllValues()
         {
             Directory directory = NewDirectory();
@@ -784,7 +784,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBytesWithNewline()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -810,7 +810,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestMissingSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -843,7 +843,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedTermsEnum()
         {
             Directory directory = NewDirectory();
@@ -916,7 +916,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestEmptySortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -948,7 +948,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestEmptyBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -980,7 +980,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestVeryLargeButLegalBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1009,7 +1009,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestVeryLargeButLegalSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1037,7 +1037,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestCodecUsesOwnBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1065,7 +1065,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestCodecUsesOwnSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1093,7 +1093,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestCodecUsesOwnBytesEachTime()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1128,7 +1128,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestCodecUsesOwnSortedBytesEachTime()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1166,7 +1166,7 @@ namespace Lucene.Net.Index
         /*
          * Simple test case to show how to use the API
          */
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocValuesSimple()
         {
             Directory dir = NewDirectory();
@@ -1211,7 +1211,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestRandomSortedBytes()
         {
             Directory dir = NewDirectory();
@@ -1488,7 +1488,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBooleanNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1498,7 +1498,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestByteNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1508,7 +1508,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestByteMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1518,7 +1518,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestShortNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1528,7 +1528,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestShortMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1538,7 +1538,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestIntNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1548,7 +1548,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestIntMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1558,7 +1558,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestLongNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1568,7 +1568,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestLongMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1643,7 +1643,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBinaryFixedLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1654,7 +1654,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBinaryVariableLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1788,7 +1788,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedFixedLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1799,7 +1799,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedFixedLengthVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1810,7 +1810,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedVariableLengthVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1820,7 +1820,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedVariableLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1830,7 +1830,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetOneValue()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1858,7 +1858,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1896,7 +1896,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoDocumentsMerged()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1941,7 +1941,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoValues()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1974,7 +1974,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoValuesUnordered()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2007,7 +2007,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetThreeValuesTwoDocs()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2059,7 +2059,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoDocumentsLastMissing()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2094,7 +2094,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoDocumentsLastMissingMerge()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2131,7 +2131,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoDocumentsFirstMissing()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2167,7 +2167,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTwoDocumentsFirstMissingMerge()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2204,7 +2204,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetMergeAwayAllValues()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2235,7 +2235,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetTermsEnum()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2391,7 +2391,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetFixedLengthVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2403,7 +2403,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetVariableLengthVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2414,7 +2414,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetFixedLengthSingleValuedVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2426,7 +2426,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetVariableLengthSingleValuedVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2648,7 +2648,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetFixedLengthVsUninvertedField()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2660,7 +2660,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetVariableLengthVsUninvertedField()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2671,7 +2671,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestGCDCompression()
         {
             int numIterations = AtLeast(1);
@@ -2704,13 +2704,13 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestZeros()
         {
             DoTestNumericsVsStoredFields(0, 0);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestZeroOrMin()
         {
             // try to make GCD compression fail if the format did not anticipate that
@@ -2738,7 +2738,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoNumbersOneMissing()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2769,7 +2769,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoNumbersOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2801,7 +2801,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestThreeNumbersOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2839,7 +2839,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoBytesOneMissing()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2873,7 +2873,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTwoBytesOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2908,7 +2908,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestThreeBytesOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2951,7 +2951,7 @@ namespace Lucene.Net.Index
         }
 
         // LUCENE-4853
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestHugeBinaryValues()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -3072,7 +3072,7 @@ namespace Lucene.Net.Index
         }
 
         // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestHugeBinaryValueLimit()
         {
             // We only test DVFormats that have a limit
@@ -3157,7 +3157,7 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestThreads()
         {
             Directory dir = NewDirectory();
@@ -3276,7 +3276,7 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Tests dv against stored fields with threads (all types + missing)
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestThreads2()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -3466,7 +3466,7 @@ namespace Lucene.Net.Index
         }
 
         // LUCENE-5218
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestEmptyBinaryValueOnPageSizes()
         {
             // Test larger and larger power-of-two sized values,

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
index d65a88b..9a49a6f 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
@@ -90,7 +90,7 @@ namespace Lucene.Net.Index
         /// <summary>
         /// The purpose of this test is to make sure that bulk merge doesn't accumulate useless data over runs.
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestMergeStability()
         {
             Directory dir = NewDirectory();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
index b9dfb8b..ffef930 100644
--- a/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
@@ -1245,43 +1245,43 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsOnly()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_ONLY, false);
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsAndFreqs()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS, false);
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsAndFreqsAndPositions()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, false);
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsAndFreqsAndPositionsAndPayloads()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, true);
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsAndFreqsAndPositionsAndOffsets()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, false);
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, true);
         }
 
-        [Test, Timeout(300000)]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestRandom()
         {
             int iters = 5;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
index a63eb84..2acb5fa 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
@@ -74,7 +74,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestRandomStoredFields()
         {
             Directory dir = NewDirectory();
@@ -190,7 +190,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         // LUCENE-1727: make sure doc fields are stored in order
         public virtual void TestStoredFieldsOrder()
         {
@@ -227,7 +227,7 @@ namespace Lucene.Net.Index
             d.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         // LUCENE-1219
         public virtual void TestBinaryFieldOffsetLength()
         {
@@ -261,7 +261,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestNumericField()
         {
             Directory dir = NewDirectory();
@@ -346,7 +346,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestIndexedBit()
         {
             Directory dir = NewDirectory();
@@ -365,7 +365,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestReadSkip()
         {
             Directory dir = NewDirectory();
@@ -420,7 +420,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test, Timeout(300000)]
+        // [Test, Timeout(300000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestEmptyDocs()
         {
             Directory dir = NewDirectory();
@@ -449,7 +449,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test, Timeout(300000)]
+        // [Test, Timeout(300000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestConcurrentReads()
         {
             Directory dir = NewDirectory();
@@ -564,7 +564,7 @@ namespace Lucene.Net.Index
             return result;
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestWriteReadMerge()
         {
             // get another codec, other than the default: so we are merging segments across different codecs
@@ -670,7 +670,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test, LongRunningTest, Timeout(int.MaxValue)]
+        // [Test, LongRunningTest, Timeout(int.MaxValue)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBigDocuments()
         {
             // "big" as "much bigger than the chunk size"
@@ -747,7 +747,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBulkMergeWithDeletes()
         {
             int numDocs = AtLeast(200);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
index 85207ad..5e5b20e 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
@@ -668,7 +668,7 @@ namespace Lucene.Net.Index
             return (new IndexSearcher(reader)).Search(new TermQuery(new Term("id", id)), 1).ScoreDocs[0].Doc;
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         // only one doc with vectors
         public virtual void TestRareVectors()
         {
@@ -715,7 +715,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestHighFreqs()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 3, 5);
@@ -737,7 +737,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test, LongRunningTest, Timeout(int.MaxValue)]
+        // [Test, LongRunningTest, Timeout(int.MaxValue)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestLotsOfFields()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 500, 10);
@@ -755,7 +755,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test, Timeout(300000)]
+        // [Test, Timeout(300000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         // different options for the same field
         public virtual void TestMixedOptions()
         {
@@ -790,7 +790,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestRandom()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 5, 20);
@@ -817,7 +817,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestMerge()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 5, 20);
@@ -866,7 +866,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         // run random tests from different threads to make sure the per-thread clones
         // don't share mutable data
         public virtual void TestClone()

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs b/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
index 2cfe630..e69ed7c 100644
--- a/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
@@ -77,7 +77,7 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Test length=0.
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestNoBit()
         {
             BitArray bs = new BitArray(1);
@@ -88,7 +88,7 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Test length=1.
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void Test1Bit()
         {
             BitArray bs = new BitArray(1);
@@ -103,7 +103,7 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Test length=2.
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void Test2Bits()
         {
             BitArray bs = new BitArray(2);
@@ -122,8 +122,8 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Compare the content of the set against a <seealso cref="BitSet"/>.
         /// </summary>
-        [Test, Timeout(150000)]
-        [LongRunningTest]
+        // [Test, Timeout(150000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        //[LongRunningTest]
         public virtual void TestAgainstBitSet()
         {
             int numBits = TestUtil.NextInt(Random(), 100, 1 << 20);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
index a66f96c..6d913b5 100644
--- a/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
@@ -38,5 +38,68 @@ namespace Lucene.Net.Codecs.BlockTerms
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
index d4e1286..d19e11a 100644
--- a/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
@@ -35,5 +35,68 @@ namespace Lucene.Net.Codecs.Bloom
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
index a0b868b..cd69092 100644
--- a/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
@@ -36,5 +36,531 @@ namespace Lucene.Net.Codecs.DiskDV
                 return codec;
             }
         }
+
+
+        #region BaseCompressingDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestUniqueValuesCompression()
+        {
+            base.TestUniqueValuesCompression();
+        }
+
+        [Test]
+        public override void TestDateCompression()
+        {
+            base.TestDateCompression();
+        }
+
+        [Test]
+        public override void TestSingleBigValueCompression()
+        {
+            base.TestSingleBigValueCompression();
+        }
+
+        #endregion
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
index 1cd9e4b..26b2684 100644
--- a/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
@@ -36,5 +36,68 @@ namespace Lucene.Net.Codecs.IntBlock
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
index 0b74a74..c255c90 100644
--- a/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
@@ -41,5 +41,68 @@ namespace Lucene.Net.Codecs.IntBlock
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file


[53/58] [abbrv] lucenenet git commit: Grouping: Fixed up documentation comments and license headers

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
index 8b5776e..175dd0a 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
@@ -5,6 +5,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// A base implementation of <see cref="AbstractAllGroupHeadsCollector{GH}"/> for retrieving the most relevant groups when grouping
     /// on a string based group field. More specifically this all concrete implementations of this base implementation
@@ -29,39 +46,48 @@ namespace Lucene.Net.Search.Grouping.Terms
         }
     }
 
+    /// <summary>
+    /// LUCENENET specific class used to mimic the synatax used to access
+    /// static members of <see cref="TermAllGroupHeadsCollector{GH}"/> without
+    /// specifying its generic closing type.
+    /// (TermAllGroupHeadsCollector.Create() rather than TermAllGroupHeadsCollector{GH}.Create()).
+    /// </summary>
     public class TermAllGroupHeadsCollector
     {
         private static readonly int DEFAULT_INITIAL_SIZE = 128;
 
-        // Disallow creation
+        /// <summary>
+        /// Disallow creation
+        /// </summary>
         private TermAllGroupHeadsCollector() { }
 
-        /**
-         * Creates an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments.
-         * This factory method decides with implementation is best suited.
-         *
-         * Delegates to {@link #create(String, org.apache.lucene.search.Sort, int)} with an initialSize of 128.
-         *
-         * @param groupField      The field to group by
-         * @param sortWithinGroup The sort within each group
-         * @return an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments
-         */
+        /// <summary>
+        /// Creates an <see cref=AbstractAllGroupHeadsCollector""/> instance based on the supplied arguments.
+        /// This factory method decides with implementation is best suited.
+        /// <para>
+        /// Delegates to <see cref="Create(string, Sort, int)"/> with an initialSize of 128.
+        /// </para>
+        /// </summary>
+        /// <param name="groupField">The field to group by</param>
+        /// <param name="sortWithinGroup">The sort within each group</param>
+        /// <returns>an <see cref="AbstractAllGroupHeadsCollector"/> instance based on the supplied arguments</returns>
         public static AbstractAllGroupHeadsCollector Create(string groupField, Sort sortWithinGroup)
         {
             return Create(groupField, sortWithinGroup, DEFAULT_INITIAL_SIZE);
         }
 
-        /**
-         * Creates an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments.
-         * This factory method decides with implementation is best suited.
-         *
-         * @param groupField      The field to group by
-         * @param sortWithinGroup The sort within each group
-         * @param initialSize The initial allocation size of the internal int set and group list which should roughly match
-         *                    the total number of expected unique groups. Be aware that the heap usage is
-         *                    4 bytes * initialSize.
-         * @return an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments
-         */
+        /// <summary>
+        /// Creates an <see cref="AbstractAllGroupHeadsCollector"/> instance based on the supplied arguments.
+        /// This factory method decides with implementation is best suited.
+        /// </summary>
+        /// <param name="groupField">The field to group by</param>
+        /// <param name="sortWithinGroup">The sort within each group</param>
+        /// <param name="initialSize">
+        /// The initial allocation size of the internal int set and group list which should roughly match
+        /// the total number of expected unique groups. Be aware that the heap usage is
+        /// 4 bytes * initialSize.
+        /// </param>
+        /// <returns>an <see cref="AbstractAllGroupHeadsCollector"/> instance based on the supplied arguments</returns>
         public static AbstractAllGroupHeadsCollector Create(string groupField, Sort sortWithinGroup, int initialSize)
         {
             bool sortAllScore = true;
@@ -97,7 +123,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        // Returns when a sort field needs the general impl.
+        /// <summary>
+        /// Returns when a sort field needs the general impl.
+        /// </summary>
         private static bool NeedGeneralImpl(SortField sortField)
         {
             SortField.Type_e sortType = sortField.Type;
@@ -106,7 +134,9 @@ namespace Lucene.Net.Search.Grouping.Terms
         }
     }
 
-    // A general impl that works for any group sort.
+    /// <summary>
+    /// A general impl that works for any group sort.
+    /// </summary>
     internal class GeneralAllGroupHeadsCollector : TermAllGroupHeadsCollector<GeneralAllGroupHeadsCollector.GroupHead>
     {
 
@@ -195,6 +225,8 @@ namespace Lucene.Net.Search.Grouping.Terms
         internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
         {
             private readonly GeneralAllGroupHeadsCollector outerInstance;
+            // LUCENENET: Moved groupValue here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
+            // need to reference the generic closing type BytesRef.
             public readonly BytesRef groupValue;
 
             internal readonly FieldComparator[] comparators;
@@ -234,10 +266,11 @@ namespace Lucene.Net.Search.Grouping.Terms
     }
 
 
-    // AbstractAllGroupHeadsCollector optimized for ord fields and scores.
+    /// <summary>
+    /// AbstractAllGroupHeadsCollector optimized for ord fields and scores.
+    /// </summary>
     internal class OrdScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdScoreAllGroupHeadsCollector.GroupHead>
     {
-        //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
         private readonly SentinelIntSet ordSet;
         private readonly IList<GroupHead> collectedGroups;
         private readonly SortField[] fields;
@@ -246,10 +279,9 @@ namespace Lucene.Net.Search.Grouping.Terms
         private Scorer scorer;
         private GroupHead[] segmentGroupHeads;
 
-        internal OrdScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+        internal OrdScoreAllGroupHeadsCollector(string groupField, Sort sortWithinGroup, int initialSize)
             : base(groupField, sortWithinGroup.GetSort().Length)
         {
-            //this.outerInstance = outerInstance;
             ordSet = new SentinelIntSet(initialSize, -2);
             collectedGroups = new List<GroupHead>(initialSize);
 
@@ -368,6 +400,8 @@ namespace Lucene.Net.Search.Grouping.Terms
         internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
         {
             private readonly OrdScoreAllGroupHeadsCollector outerInstance;
+            // LUCENENET: Moved groupValue here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
+            // need to reference the generic closing type BytesRef.
             public readonly BytesRef groupValue;
 
             internal BytesRef[] sortValues;
@@ -465,10 +499,11 @@ namespace Lucene.Net.Search.Grouping.Terms
     }
 
 
-    // AbstractAllGroupHeadsCollector optimized for ord fields.
+    /// <summary>
+    /// AbstractAllGroupHeadsCollector optimized for ord fields.
+    /// </summary>
     internal class OrdAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdAllGroupHeadsCollector.GroupHead>
     {
-        //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
         private readonly SentinelIntSet ordSet;
         private readonly IList<GroupHead> collectedGroups;
         private readonly SortField[] fields;
@@ -476,10 +511,9 @@ namespace Lucene.Net.Search.Grouping.Terms
         private SortedDocValues[] sortsIndex;
         private GroupHead[] segmentGroupHeads;
 
-        internal OrdAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+        internal OrdAllGroupHeadsCollector(string groupField, Sort sortWithinGroup, int initialSize)
                     : base(groupField, sortWithinGroup.GetSort().Length)
         {
-            //this.outerInstance = outerInstance;
             ordSet = new SentinelIntSet(initialSize, -2);
             collectedGroups = new List<GroupHead>(initialSize);
 
@@ -587,6 +621,8 @@ namespace Lucene.Net.Search.Grouping.Terms
         internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /* AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
         {
             private readonly OrdAllGroupHeadsCollector outerInstance;
+            // LUCENENET: Moved groupValue here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
+            // need to reference the generic closing type BytesRef.
             public readonly BytesRef groupValue;
             internal BytesRef[] sortValues;
             internal int[] sortOrds;
@@ -653,10 +689,11 @@ namespace Lucene.Net.Search.Grouping.Terms
     }
 
 
-    // AbstractAllGroupHeadsCollector optimized for scores.
+    /// <summary>
+    /// AbstractAllGroupHeadsCollector optimized for scores.
+    /// </summary>
     internal class ScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<ScoreAllGroupHeadsCollector.GroupHead>
     {
-        //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
         private readonly SentinelIntSet ordSet;
         private readonly IList<GroupHead> collectedGroups;
         private readonly SortField[] fields;
@@ -664,10 +701,9 @@ namespace Lucene.Net.Search.Grouping.Terms
         private Scorer scorer;
         private GroupHead[] segmentGroupHeads;
 
-        internal ScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+        internal ScoreAllGroupHeadsCollector(string groupField, Sort sortWithinGroup, int initialSize)
                     : base(groupField, sortWithinGroup.GetSort().Length)
         {
-            //this.outerInstance = outerInstance;
             ordSet = new SentinelIntSet(initialSize, -2);
             collectedGroups = new List<GroupHead>(initialSize);
 
@@ -755,7 +791,7 @@ namespace Lucene.Net.Search.Grouping.Terms
         internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead
         {
             private readonly ScoreAllGroupHeadsCollector outerInstance;
-            // LUCENENET: Moved this here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
+            // LUCENENET: Moved groupValue here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
             // need to reference the generic closing type BytesRef.
             public readonly BytesRef groupValue;
             internal float[] scores;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
index 953bb82..17b0438 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
@@ -5,6 +5,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// A collector that collects all groups that match the
     /// query. Only the group value is collected, and the order

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
index 91bc674..a41cba3 100644
--- a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
@@ -7,6 +7,23 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// A term based implementation of <see cref="AbstractDistinctValuesCollector{TermDistinctValuesCollector.GroupCount}"/> that relies
     /// on <see cref="SortedDocValues"/> to count the distinct values per group.
@@ -24,13 +41,12 @@ namespace Lucene.Net.Search.Grouping.Terms
         private SortedDocValues groupFieldTermIndex;
         private SortedDocValues countFieldTermIndex;
 
-        /**
-         * Constructs {@link TermDistinctValuesCollector} instance.
-         *
-         * @param groupField The field to group by
-         * @param countField The field to count distinct values for
-         * @param groups The top N groups, collected during the first phase search
-         */
+        /// <summary>
+        /// Constructs <see cref="TermDistinctValuesCollector"/> instance.
+        /// </summary>
+        /// <param name="groupField">The field to group by</param>
+        /// <param name="countField">The field to count distinct values for</param>
+        /// <param name="groups">The top N groups, collected during the first phase search</param>
         public TermDistinctValuesCollector(string groupField, string countField, IEnumerable<ISearchGroup<BytesRef>> groups)
         {
             this.groupField = groupField;
@@ -126,9 +142,11 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        /** Holds distinct values for a single group.
-         *
-         * @lucene.experimental */
+        /// <summary>
+        /// Holds distinct values for a single group.
+        /// 
+        /// @lucene.experimental
+        /// </summary>
         public class GroupCount : AbstractDistinctValuesCollector.GroupCount<BytesRef>
         {
             internal int[] ords;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
index 9f61ae7..20775f9 100644
--- a/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
@@ -3,6 +3,23 @@ using Lucene.Net.Util;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Concrete implementation of <see cref="AbstractFirstPassGroupingCollector{BytesRef}"/> that groups based on
     /// field values and more specifically uses <see cref="SortedDocValues"/>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs b/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
index e694ef2..690e31e 100644
--- a/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
@@ -5,6 +5,23 @@ using System.Diagnostics;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// An implementation of <see cref="AbstractGroupFacetCollector"/> that computes grouped facets based on the indexed terms
     /// from the <see cref="FieldCache"/>.
@@ -18,19 +35,20 @@ namespace Lucene.Net.Search.Grouping.Terms
 
         internal SortedDocValues groupFieldTermsIndex;
 
-        /**
-         * Factory method for creating the right implementation based on the fact whether the facet field contains
-         * multiple tokens per documents.
-         *
-         * @param groupField The group field
-         * @param facetField The facet field
-         * @param facetFieldMultivalued Whether the facet field has multiple tokens per document
-         * @param facetPrefix The facet prefix a facet entry should start with to be included.
-         * @param initialSize The initial allocation size of the internal int set and group facet list which should roughly
-         *                    match the total number of expected unique groups. Be aware that the heap usage is
-         *                    4 bytes * initialSize.
-         * @return <code>TermGroupFacetCollector</code> implementation
-         */
+        /// <summary>
+        /// Factory method for creating the right implementation based on the fact whether the facet field contains
+        /// multiple tokens per documents.
+        /// </summary>
+        /// <param name="groupField">The group field</param>
+        /// <param name="facetField">The facet field</param>
+        /// <param name="facetFieldMultivalued">Whether the facet field has multiple tokens per document</param>
+        /// <param name="facetPrefix">The facet prefix a facet entry should start with to be included.</param>
+        /// <param name="initialSize">
+        /// The initial allocation size of the internal int set and group facet list which should roughly
+        /// match the total number of expected unique groups. Be aware that the heap usage is
+        /// 4 bytes * initialSize.
+        /// </param>
+        /// <returns><see cref="TermGroupFacetCollector"/> implementation</returns>
         public static TermGroupFacetCollector CreateTermGroupFacetCollector(string groupField,
                                                                             string facetField,
                                                                             bool facetFieldMultivalued,
@@ -54,7 +72,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             segmentGroupedFacetHits = new SentinelIntSet(initialSize, int.MinValue);
         }
 
-        // Implementation for single valued facet fields.
+        /// <summary>
+        /// Implementation for single valued facet fields.
+        /// </summary>
         internal class SV : TermGroupFacetCollector
         {
 
@@ -198,7 +218,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        // Implementation for multi valued facet fields.
+        /// <summary>
+        /// Implementation for multi valued facet fields.
+        /// </summary>
         internal class MV : TermGroupFacetCollector
         {
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
index c9de6c1..22b0365 100644
--- a/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
@@ -4,6 +4,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Concrete implementation of <see cref="AbstractSecondPassGroupingCollector{BytesRef}"/> that groups based on
     /// field values and more specifically uses <see cref="SortedDocValues"/>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/TopGroups.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/TopGroups.cs b/src/Lucene.Net.Grouping/TopGroups.cs
index d66439d..d8a2165 100644
--- a/src/Lucene.Net.Grouping/TopGroups.cs
+++ b/src/Lucene.Net.Grouping/TopGroups.cs
@@ -260,7 +260,7 @@ namespace Lucene.Net.Search.Grouping
 
     /// <summary>
     /// LUCENENET specific interface used to provide covariance
-    /// with the TGroupValue type
+    /// with the TGroupValue type to simulate Java's wildcard generics.
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
     public interface ITopGroups<out TGroupValue>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
index 74a926a..d434a80 100644
--- a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
+++ b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
@@ -3,6 +3,23 @@ using System;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Base class for grouping related tests.
     /// </summary>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index c7cac67..8d6ca76 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -17,6 +17,23 @@ using System.Text;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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 AllGroupHeadsCollectorTest : LuceneTestCase
     {
         private static readonly FieldInfo.DocValuesType_e[] vts = new FieldInfo.DocValuesType_e[]{

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
index 2d42c43..28aa28d 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
@@ -13,6 +13,23 @@ using System.Collections;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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 AllGroupsCollectorTest : LuceneTestCase
     {
         [Test]

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
index 711f339..5ef9589 100644
--- a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
@@ -17,6 +17,23 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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 DistinctValuesCollectorTest : AbstractGroupingTestCase
     {
         private readonly static NullComparator nullComparator = new NullComparator();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
index e50c91b..c4fc0dc 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
@@ -14,6 +14,23 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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 GroupFacetCollectorTest : AbstractGroupingTestCase
     {
         [Test]

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
index 49b56e6..bb8dca2 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
@@ -13,6 +13,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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 GroupingSearchTest : LuceneTestCase
     {
         // Tests some very basic usages...


[31/58] [abbrv] lucenenet git commit: WIP on Grouping

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
new file mode 100644
index 0000000..fbbec34
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
@@ -0,0 +1,807 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping.Terms
+{
+    /// <summary>
+    /// A base implementation of <see cref="AbstractAllGroupHeadsCollector{GH}"/> for retrieving the most relevant groups when grouping
+    /// on a string based group field. More specifically this all concrete implementations of this base implementation
+    /// use <see cref="Index.SortedDocValues"/>.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="GH"></typeparam>
+    public abstract class TermAllGroupHeadsCollector<GH> : AbstractAllGroupHeadsCollector<GH> where GH : AbstractGroupHead /*AbstractAllGroupHeadsCollector<GH>.GroupHead*/
+    {
+        internal readonly string groupField;
+        internal readonly BytesRef scratchBytesRef = new BytesRef();
+
+        internal SortedDocValues groupIndex;
+        internal AtomicReaderContext readerContext;
+
+        protected TermAllGroupHeadsCollector(string groupField, int numberOfSorts)
+            : base(numberOfSorts)
+        {
+            this.groupField = groupField;
+        }
+    }
+
+    public class TermAllGroupHeadsCollector
+    {
+        private static readonly int DEFAULT_INITIAL_SIZE = 128;
+
+        // Disallow creation
+        private TermAllGroupHeadsCollector() { }
+
+        /**
+         * Creates an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments.
+         * This factory method decides with implementation is best suited.
+         *
+         * Delegates to {@link #create(String, org.apache.lucene.search.Sort, int)} with an initialSize of 128.
+         *
+         * @param groupField      The field to group by
+         * @param sortWithinGroup The sort within each group
+         * @return an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments
+         */
+        public static AbstractAllGroupHeadsCollector Create(string groupField, Sort sortWithinGroup)
+        {
+            return Create(groupField, sortWithinGroup, DEFAULT_INITIAL_SIZE);
+        }
+
+        /**
+         * Creates an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments.
+         * This factory method decides with implementation is best suited.
+         *
+         * @param groupField      The field to group by
+         * @param sortWithinGroup The sort within each group
+         * @param initialSize The initial allocation size of the internal int set and group list which should roughly match
+         *                    the total number of expected unique groups. Be aware that the heap usage is
+         *                    4 bytes * initialSize.
+         * @return an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments
+         */
+        public static AbstractAllGroupHeadsCollector Create(string groupField, Sort sortWithinGroup, int initialSize)
+        {
+            bool sortAllScore = true;
+            bool sortAllFieldValue = true;
+
+            foreach (SortField sortField in sortWithinGroup.GetSort())
+            {
+                if (sortField.Type == SortField.Type_e.SCORE)
+                {
+                    sortAllFieldValue = false;
+                }
+                else if (NeedGeneralImpl(sortField))
+                {
+                    return new GeneralAllGroupHeadsCollector(groupField, sortWithinGroup);
+                }
+                else
+                {
+                    sortAllScore = false;
+                }
+            }
+
+            if (sortAllScore)
+            {
+                return new ScoreAllGroupHeadsCollector(groupField, sortWithinGroup, initialSize);
+            }
+            else if (sortAllFieldValue)
+            {
+                return new OrdAllGroupHeadsCollector(groupField, sortWithinGroup, initialSize);
+            }
+            else
+            {
+                return new OrdScoreAllGroupHeadsCollector(groupField, sortWithinGroup, initialSize);
+            }
+        }
+
+        // Returns when a sort field needs the general impl.
+        private static bool NeedGeneralImpl(SortField sortField)
+        {
+            SortField.Type_e sortType = sortField.Type;
+            // Note (MvG): We can also make an optimized impl when sorting is SortField.DOC
+            return sortType != SortField.Type_e.STRING_VAL && sortType != SortField.Type_e.STRING && sortType != SortField.Type_e.SCORE;
+        }
+    }
+
+    // A general impl that works for any group sort.
+    internal class GeneralAllGroupHeadsCollector : TermAllGroupHeadsCollector<GeneralAllGroupHeadsCollector.GroupHead>
+        {
+
+            private readonly Sort sortWithinGroup;
+            private readonly IDictionary<BytesRef, GroupHead> groups;
+
+            internal Scorer scorer;
+
+            internal GeneralAllGroupHeadsCollector(string groupField, Sort sortWithinGroup)
+                : base(groupField, sortWithinGroup.GetSort().Length)
+            {
+                this.sortWithinGroup = sortWithinGroup;
+                groups = new HashMap<BytesRef, GroupHead>();
+
+                SortField[] sortFields = sortWithinGroup.GetSort();
+                for (int i = 0; i < sortFields.Length; i++)
+                {
+                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                }
+            }
+
+            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+            {
+                int ord = groupIndex.GetOrd(doc);
+                BytesRef groupValue;
+                if (ord == -1)
+                {
+                    groupValue = null;
+                }
+                else
+                {
+                    groupIndex.LookupOrd(ord, scratchBytesRef);
+                    groupValue = scratchBytesRef;
+                }
+                GroupHead groupHead;
+                if (!groups.TryGetValue(groupValue, out groupHead))
+                {
+                    groupHead = new GroupHead(this, groupValue, sortWithinGroup, doc);
+                    groups[groupValue == null ? null : BytesRef.DeepCopyOf(groupValue)] = groupHead;
+                    temporalResult.stop = true;
+                }
+                else
+                {
+                    temporalResult.stop = false;
+                }
+                temporalResult.groupHead = groupHead;
+            }
+
+            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            {
+                return groups.Values;
+            }
+
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    this.readerContext = value;
+                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+
+                    foreach (GroupHead groupHead in groups.Values)
+                    {
+                        for (int i = 0; i < groupHead.comparators.Length; i++)
+                        {
+                            groupHead.comparators[i] = groupHead.comparators[i].SetNextReader(value);
+                        }
+                    }
+                }
+            }
+
+            public override Scorer Scorer
+            {
+                set
+                {
+                    this.scorer = value;
+                    foreach (GroupHead groupHead in groups.Values)
+                    {
+                        foreach (FieldComparator comparator in groupHead.comparators)
+                        {
+                            comparator.Scorer = value;
+                        }
+                    }
+                }
+            }
+
+            internal class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+            {
+                private readonly GeneralAllGroupHeadsCollector outerInstance;
+                public readonly BytesRef groupValue;
+
+                internal readonly FieldComparator[] comparators;
+
+                internal GroupHead(GeneralAllGroupHeadsCollector outerInstance, BytesRef groupValue, Sort sort, int doc)
+                    : base(doc + outerInstance.readerContext.DocBase)
+                {
+                    this.outerInstance = outerInstance;
+                    SortField[] sortFields = sort.GetSort();
+                    comparators = new FieldComparator[sortFields.Length];
+                    for (int i = 0; i < sortFields.Length; i++)
+                    {
+                        comparators[i] = sortFields[i].GetComparator(1, i).SetNextReader(outerInstance.readerContext);
+                        comparators[i].Scorer = outerInstance.scorer;
+                        comparators[i].Copy(0, doc);
+                        comparators[i].Bottom = 0;
+                    }
+                }
+
+                public override int Compare(int compIDX, int doc)
+                {
+                    return comparators[compIDX].CompareBottom(doc);
+                }
+
+                public override void UpdateDocHead(int doc)
+                {
+                    foreach (FieldComparator comparator in comparators)
+                    {
+                        comparator.Copy(0, doc);
+                        comparator.Bottom = 0;
+                    }
+                    this.Doc = doc + outerInstance.readerContext.DocBase;
+                }
+            }
+        }
+
+
+        // AbstractAllGroupHeadsCollector optimized for ord fields and scores.
+        internal class OrdScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdScoreAllGroupHeadsCollector.GroupHead>
+        {
+            //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
+            private readonly SentinelIntSet ordSet;
+            private readonly IList<GroupHead> collectedGroups;
+            private readonly SortField[] fields;
+
+            private SortedDocValues[] sortsIndex;
+            private Scorer scorer;
+            private GroupHead[] segmentGroupHeads;
+
+            internal OrdScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+                : base(groupField, sortWithinGroup.GetSort().Length)
+            {
+                //this.outerInstance = outerInstance;
+                ordSet = new SentinelIntSet(initialSize, -2);
+                collectedGroups = new List<GroupHead>(initialSize);
+
+                SortField[] sortFields = sortWithinGroup.GetSort();
+                fields = new SortField[sortFields.Length];
+                sortsIndex = new SortedDocValues[sortFields.Length];
+                for (int i = 0; i < sortFields.Length; i++)
+                {
+                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                    fields[i] = sortFields[i];
+                }
+            }
+
+            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            {
+                return collectedGroups;
+            }
+
+            public override Scorer Scorer
+            {
+                set
+                {
+                    this.scorer = value;
+                }
+            }
+
+
+            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+            {
+                int key = groupIndex.GetOrd(doc);
+                GroupHead groupHead;
+                if (!ordSet.Exists(key))
+                {
+                    ordSet.Put(key);
+                    BytesRef term;
+                    if (key == -1)
+                    {
+                        term = null;
+                    }
+                    else
+                    {
+                        term = new BytesRef();
+                        groupIndex.LookupOrd(key, term);
+                    }
+                    groupHead = new GroupHead(this, doc, term);
+                    collectedGroups.Add(groupHead);
+                    segmentGroupHeads[key + 1] = groupHead;
+                    temporalResult.stop = true;
+                }
+                else
+                {
+                    temporalResult.stop = false;
+                    groupHead = segmentGroupHeads[key + 1];
+                }
+                temporalResult.groupHead = groupHead;
+            }
+
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    this.readerContext = value;
+                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                    for (int i = 0; i < fields.Length; i++)
+                    {
+                        if (fields[i].Type == SortField.Type_e.SCORE)
+                        {
+                            continue;
+                        }
+
+                        sortsIndex[i] = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, fields[i].Field);
+                    }
+
+                    // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                    ordSet.Clear();
+                    segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
+                    foreach (GroupHead collectedGroup in collectedGroups)
+                    {
+                        int ord;
+                        if (collectedGroup.groupValue == null)
+                        {
+                            ord = -1;
+                        }
+                        else
+                        {
+                            ord = groupIndex.LookupTerm(collectedGroup.groupValue);
+                        }
+                        if (collectedGroup.groupValue == null || ord >= 0)
+                        {
+                            ordSet.Put(ord);
+                            segmentGroupHeads[ord + 1] = collectedGroup;
+
+                            for (int i = 0; i < sortsIndex.Length; i++)
+                            {
+                                if (fields[i].Type == SortField.Type_e.SCORE)
+                                {
+                                    continue;
+                                }
+                                int sortOrd;
+                                if (collectedGroup.sortValues[i] == null)
+                                {
+                                    sortOrd = -1;
+                                }
+                                else
+                                {
+                                    sortOrd = sortsIndex[i].LookupTerm(collectedGroup.sortValues[i]);
+                                }
+                                collectedGroup.sortOrds[i] = sortOrd;
+                            }
+                        }
+                    }
+                }
+
+            }
+
+            internal class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+            {
+                private readonly OrdScoreAllGroupHeadsCollector outerInstance;
+                public readonly BytesRef groupValue;
+
+                internal BytesRef[] sortValues;
+                internal int[] sortOrds;
+                internal float[] scores;
+
+                internal GroupHead(OrdScoreAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
+                    : base(doc + outerInstance.readerContext.DocBase)
+                {
+                    this.outerInstance = outerInstance;
+                    this.groupValue = groupValue;
+
+                    sortValues = new BytesRef[outerInstance.sortsIndex.Length];
+                    sortOrds = new int[outerInstance.sortsIndex.Length];
+                    scores = new float[outerInstance.sortsIndex.Length];
+                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    {
+                        if (outerInstance.fields[i].Type == SortField.Type_e.SCORE)
+                        {
+                            scores[i] = outerInstance.scorer.Score();
+                        }
+                        else
+                        {
+                            sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                            sortValues[i] = new BytesRef();
+                            if (sortOrds[i] != -1)
+                            {
+                                outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
+                            }
+                        }
+                    }
+                }
+
+                public override int Compare(int compIDX, int doc)
+                {
+                    if (outerInstance.fields[compIDX].Type == SortField.Type_e.SCORE)
+                    {
+                        float score = outerInstance.scorer.Score();
+                        if (scores[compIDX] < score)
+                        {
+                            return 1;
+                        }
+                        else if (scores[compIDX] > score)
+                        {
+                            return -1;
+                        }
+                        return 0;
+                    }
+                    else
+                    {
+                        if (sortOrds[compIDX] < 0)
+                        {
+                            // The current segment doesn't contain the sort value we encountered before. Therefore the ord is negative.
+                            if (outerInstance.sortsIndex[compIDX].GetOrd(doc) == -1)
+                            {
+                                outerInstance.scratchBytesRef.Length = 0;
+                            }
+                            else
+                            {
+                                outerInstance.sortsIndex[compIDX].Get(doc, outerInstance.scratchBytesRef);
+                            }
+                            return sortValues[compIDX].CompareTo(outerInstance.scratchBytesRef);
+                        }
+                        else
+                        {
+                            return sortOrds[compIDX] - outerInstance.sortsIndex[compIDX].GetOrd(doc);
+                        }
+                    }
+                }
+
+                public override void UpdateDocHead(int doc)
+                {
+                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    {
+                        if (outerInstance.fields[i].Type == Search.SortField.Type_e.SCORE)
+                        {
+                            scores[i] = outerInstance.scorer.Score();
+                        }
+                        else
+                        {
+                            sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                            if (sortOrds[i] == -1)
+                            {
+                                sortValues[i].Length = 0;
+                            }
+                            else
+                            {
+                                outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
+                            }
+                        }
+                    }
+                    this.Doc = doc + outerInstance.readerContext.DocBase;
+                }
+            }
+        }
+
+
+        // AbstractAllGroupHeadsCollector optimized for ord fields.
+        internal class OrdAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdAllGroupHeadsCollector.GroupHead>
+        {
+            //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
+            private readonly SentinelIntSet ordSet;
+            private readonly IList<GroupHead> collectedGroups;
+            private readonly SortField[] fields;
+
+            private SortedDocValues[] sortsIndex;
+            private GroupHead[] segmentGroupHeads;
+
+            internal OrdAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+                        : base(groupField, sortWithinGroup.GetSort().Length)
+            {
+                //this.outerInstance = outerInstance;
+                ordSet = new SentinelIntSet(initialSize, -2);
+                collectedGroups = new List<GroupHead>(initialSize);
+
+                SortField[] sortFields = sortWithinGroup.GetSort();
+                fields = new SortField[sortFields.Length];
+                sortsIndex = new SortedDocValues[sortFields.Length];
+                for (int i = 0; i < sortFields.Length; i++)
+                {
+                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                    fields[i] = sortFields[i];
+                }
+            }
+
+            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            {
+                return collectedGroups;
+            }
+
+            public override Scorer Scorer
+            {
+                set
+                {
+                }
+            }
+
+
+            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+            {
+                int key = groupIndex.GetOrd(doc);
+                GroupHead groupHead;
+                if (!ordSet.Exists(key))
+                {
+                    ordSet.Put(key);
+                    BytesRef term;
+                    if (key == -1)
+                    {
+                        term = null;
+                    }
+                    else
+                    {
+                        term = new BytesRef();
+                        groupIndex.LookupOrd(key, term);
+                    }
+                    groupHead = new GroupHead(this, doc, term);
+                    collectedGroups.Add(groupHead);
+                    segmentGroupHeads[key + 1] = groupHead;
+                    temporalResult.stop = true;
+                }
+                else
+                {
+                    temporalResult.stop = false;
+                    groupHead = segmentGroupHeads[key + 1];
+                }
+                temporalResult.groupHead = groupHead;
+            }
+
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    this.readerContext = value;
+                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                    for (int i = 0; i < fields.Length; i++)
+                    {
+                        sortsIndex[i] = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, fields[i].Field);
+                    }
+
+                    // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                    ordSet.Clear();
+                    segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
+                    foreach (GroupHead collectedGroup in collectedGroups)
+                    {
+                        int groupOrd;
+                        if (collectedGroup.groupValue == null)
+                        {
+                            groupOrd = -1;
+                        }
+                        else
+                        {
+                            groupOrd = groupIndex.LookupTerm(collectedGroup.groupValue);
+                        }
+                        if (collectedGroup.groupValue == null || groupOrd >= 0)
+                        {
+                            ordSet.Put(groupOrd);
+                            segmentGroupHeads[groupOrd + 1] = collectedGroup;
+
+                            for (int i = 0; i < sortsIndex.Length; i++)
+                            {
+                                int sortOrd;
+                                if (collectedGroup.sortOrds[i] == -1)
+                                {
+                                    sortOrd = -1;
+                                }
+                                else
+                                {
+                                    sortOrd = sortsIndex[i].LookupTerm(collectedGroup.sortValues[i]);
+                                }
+                                collectedGroup.sortOrds[i] = sortOrd;
+                            }
+                        }
+                    }
+                }
+            }
+
+            internal class GroupHead : AbstractGroupHead /* AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+            {
+                private readonly OrdAllGroupHeadsCollector outerInstance;
+                public readonly BytesRef groupValue;
+                internal BytesRef[] sortValues;
+                internal int[] sortOrds;
+
+                internal GroupHead(OrdAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
+                    : base(doc + outerInstance.readerContext.DocBase)
+                {
+                    this.outerInstance = outerInstance;
+                    this.groupValue = groupValue;
+
+                    sortValues = new BytesRef[outerInstance.sortsIndex.Length];
+                    sortOrds = new int[outerInstance.sortsIndex.Length];
+                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    {
+                        sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                        sortValues[i] = new BytesRef();
+                        if (sortOrds[i] != -1)
+                        {
+                            outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
+                        }
+                    }
+                }
+
+                public override int Compare(int compIDX, int doc)
+                {
+                    if (sortOrds[compIDX] < 0)
+                    {
+                        // The current segment doesn't contain the sort value we encountered before. Therefore the ord is negative.
+                        if (outerInstance.sortsIndex[compIDX].GetOrd(doc) == -1)
+                        {
+                            outerInstance.scratchBytesRef.Length = 0;
+                        }
+                        else
+                        {
+                            outerInstance.sortsIndex[compIDX].Get(doc, outerInstance.scratchBytesRef);
+                        }
+                        return sortValues[compIDX].CompareTo(outerInstance.scratchBytesRef);
+                    }
+                    else
+                    {
+                        return sortOrds[compIDX] - outerInstance.sortsIndex[compIDX].GetOrd(doc);
+                    }
+                }
+
+                public override void UpdateDocHead(int doc)
+                {
+                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    {
+                        sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                        if (sortOrds[i] == -1)
+                        {
+                            sortValues[i].Length = 0;
+                        }
+                        else
+                        {
+                            outerInstance.sortsIndex[i].LookupOrd(sortOrds[i], sortValues[i]);
+                        }
+                    }
+                    this.Doc = doc + outerInstance.readerContext.DocBase;
+                }
+
+            }
+
+        }
+
+
+        // AbstractAllGroupHeadsCollector optimized for scores.
+        internal class ScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<ScoreAllGroupHeadsCollector.GroupHead>
+        {
+            //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
+            private readonly SentinelIntSet ordSet;
+            private readonly IList<GroupHead> collectedGroups;
+            private readonly SortField[] fields;
+
+            private Scorer scorer;
+            private GroupHead[] segmentGroupHeads;
+
+            internal ScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+                        : base(groupField, sortWithinGroup.GetSort().Length)
+            {
+                //this.outerInstance = outerInstance;
+                ordSet = new SentinelIntSet(initialSize, -2);
+                collectedGroups = new List<GroupHead>(initialSize);
+
+                SortField[] sortFields = sortWithinGroup.GetSort();
+                fields = new SortField[sortFields.Length];
+                for (int i = 0; i < sortFields.Length; i++)
+                {
+                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                    fields[i] = sortFields[i];
+                }
+            }
+
+            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            {
+                return collectedGroups;
+            }
+
+            public override Scorer Scorer
+            {
+                set
+                {
+                    this.scorer = value;
+                }
+            }
+
+            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+            {
+                int key = groupIndex.GetOrd(doc);
+                GroupHead groupHead;
+                if (!ordSet.Exists(key))
+                {
+                    ordSet.Put(key);
+                    BytesRef term;
+                    if (key == -1)
+                    {
+                        term = null;
+                    }
+                    else
+                    {
+                        term = new BytesRef();
+                        groupIndex.LookupOrd(key, term);
+                    }
+                    groupHead = new GroupHead(this, doc, term);
+                    collectedGroups.Add(groupHead);
+                    segmentGroupHeads[key + 1] = groupHead;
+                    temporalResult.stop = true;
+                }
+                else
+                {
+                    temporalResult.stop = false;
+                    groupHead = segmentGroupHeads[key + 1];
+                }
+                temporalResult.groupHead = groupHead;
+            }
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    this.readerContext = value;
+                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+
+                    // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                    ordSet.Clear();
+                    segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
+                    foreach (GroupHead collectedGroup in collectedGroups)
+                    {
+                        int ord;
+                        if (collectedGroup.groupValue == null)
+                        {
+                            ord = -1;
+                        }
+                        else
+                        {
+                            ord = groupIndex.LookupTerm(collectedGroup.groupValue);
+                        }
+                        if (collectedGroup.groupValue == null || ord >= 0)
+                        {
+                            ordSet.Put(ord);
+                            segmentGroupHeads[ord + 1] = collectedGroup;
+                        }
+                    }
+                }
+            }
+
+            internal class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+            {
+                private readonly ScoreAllGroupHeadsCollector outerInstance;
+                public readonly BytesRef groupValue;
+                internal float[] scores;
+
+                internal GroupHead(ScoreAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
+                    : base(doc + outerInstance.readerContext.DocBase)
+                {
+                    this.outerInstance = outerInstance;
+                    this.groupValue = groupValue;
+
+                    scores = new float[outerInstance.fields.Length];
+                    float score = outerInstance.scorer.Score();
+                    for (int i = 0; i < scores.Length; i++)
+                    {
+                        scores[i] = score;
+                    }
+                }
+
+                public override int Compare(int compIDX, int doc)
+                {
+                    float score = outerInstance.scorer.Score();
+                    if (scores[compIDX] < score)
+                    {
+                        return 1;
+                    }
+                    else if (scores[compIDX] > score)
+                    {
+                        return -1;
+                    }
+                    return 0;
+                }
+
+                public override void UpdateDocHead(int doc)
+                {
+                    float score = outerInstance.scorer.Score();
+                    for (int i = 0; i < scores.Length; i++)
+                    {
+                        scores[i] = score;
+                    }
+                    this.Doc = doc + outerInstance.readerContext.DocBase;
+                }
+
+            }
+
+        
+
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
new file mode 100644
index 0000000..7693d93
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
@@ -0,0 +1,120 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping.Terms
+{
+    /// <summary>
+    /// A collector that collects all groups that match the
+    /// query. Only the group value is collected, and the order
+    /// is undefined.  This collector does not determine
+    /// the most relevant document of a group.
+    /// 
+    /// <para>
+    /// Implementation detail: an int hash set (SentinelIntSet)
+    /// is used to detect if a group is already added to the
+    /// total count.  For each segment the int set is cleared and filled
+    /// with previous counted groups that occur in the new
+    /// segment.
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
+    public class TermAllGroupsCollector : AbstractAllGroupsCollector<BytesRef>
+    {
+        private static readonly int DEFAULT_INITIAL_SIZE = 128;
+
+        private readonly String groupField;
+        private readonly SentinelIntSet ordSet;
+        private readonly IList<BytesRef> groups;
+
+        private SortedDocValues index;
+
+        /// <summary>
+        /// Expert: Constructs a <see cref="AbstractAllGroupsCollector{BytesRef}"/>
+        /// </summary>
+        /// <param name="groupField">The field to group by</param>
+        /// <param name="initialSize">
+        /// The initial allocation size of the
+        /// internal int set and group list
+        /// which should roughly match the total
+        /// number of expected unique groups. Be aware that the
+        /// heap usage is 4 bytes * initialSize.
+        /// </param>
+        public TermAllGroupsCollector(string groupField, int initialSize)
+        {
+            ordSet = new SentinelIntSet(initialSize, -2);
+            groups = new List<BytesRef>(initialSize);
+            this.groupField = groupField;
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="AbstractAllGroupsCollector{BytesRef}"/>. This sets the
+        /// initial allocation size for the internal int set and group
+        /// list to 128.
+        /// </summary>
+        /// <param name="groupField">The field to group by</param>
+        public TermAllGroupsCollector(string groupField)
+            : this(groupField, DEFAULT_INITIAL_SIZE)
+        {
+        }
+
+        public override void Collect(int doc)
+        {
+            int key = index.GetOrd(doc);
+            if (!ordSet.Exists(key))
+            {
+                ordSet.Put(key);
+                BytesRef term;
+                if (key == -1)
+                {
+                    term = null;
+                }
+                else
+                {
+                    term = new BytesRef();
+                    index.LookupOrd(key, term);
+                }
+                groups.Add(term);
+            }
+        }
+
+        public override ICollection<BytesRef> Groups
+        {
+            get
+            {
+                return groups;
+            }
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                index = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+
+                // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                ordSet.Clear();
+                foreach (BytesRef countedGroup in groups)
+                {
+                    if (countedGroup == null)
+                    {
+                        ordSet.Put(-1);
+                    }
+                    else
+                    {
+                        int ord = index.LookupTerm(countedGroup);
+                        if (ord >= 0)
+                        {
+                            ordSet.Put(ord);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
new file mode 100644
index 0000000..d6f6bab
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Term/TermDistinctValuesCollector.cs
@@ -0,0 +1,144 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping.Terms
+{
+    /// <summary>
+    /// A term based implementation of <see cref="AbstractDistinctValuesCollector{TermDistinctValuesCollector.GroupCount}"/> that relies
+    /// on <see cref="SortedDocValues"/> to count the distinct values per group.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class TermDistinctValuesCollector : AbstractDistinctValuesCollector<TermDistinctValuesCollector.GroupCount>
+    {
+        private readonly string groupField;
+        private readonly string countField;
+        private readonly List<GroupCount> groups;
+        private readonly SentinelIntSet ordSet;
+        private readonly GroupCount[] groupCounts;
+
+        private SortedDocValues groupFieldTermIndex;
+        private SortedDocValues countFieldTermIndex;
+
+        /**
+         * Constructs {@link TermDistinctValuesCollector} instance.
+         *
+         * @param groupField The field to group by
+         * @param countField The field to count distinct values for
+         * @param groups The top N groups, collected during the first phase search
+         */
+        public TermDistinctValuesCollector(string groupField, string countField, ICollection<SearchGroup<BytesRef>> groups)
+        {
+            this.groupField = groupField;
+            this.countField = countField;
+            this.groups = new List<GroupCount>(groups.Count);
+            foreach (SearchGroup<BytesRef> group in groups)
+            {
+                this.groups.Add(new GroupCount(group.groupValue));
+            }
+            ordSet = new SentinelIntSet(groups.Count, -2);
+            groupCounts = new GroupCount[ordSet.Keys.Length];
+        }
+
+        public override void Collect(int doc)
+        {
+            int slot = ordSet.Find(groupFieldTermIndex.GetOrd(doc));
+            if (slot < 0)
+            {
+                return;
+            }
+
+            GroupCount gc = groupCounts[slot];
+            int countOrd = countFieldTermIndex.GetOrd(doc);
+            if (DoesNotContainOrd(countOrd, gc.ords))
+            {
+                if (countOrd == -1)
+                {
+                    gc.uniqueValues.Add(null);
+                }
+                else
+                {
+                    BytesRef br = new BytesRef();
+                    countFieldTermIndex.LookupOrd(countOrd, br);
+                    gc.uniqueValues.Add(br);
+                }
+
+                gc.ords = Arrays.CopyOf(gc.ords, gc.ords.Length + 1);
+                gc.ords[gc.ords.Length - 1] = countOrd;
+                if (gc.ords.Length > 1)
+                {
+                    Array.Sort(gc.ords);
+                }
+            }
+        }
+
+        private bool DoesNotContainOrd(int ord, int[] ords)
+        {
+            if (ords.Length == 0)
+            {
+                return true;
+            }
+            else if (ords.Length == 1)
+            {
+                return ord != ords[0];
+            }
+            return Array.BinarySearch(ords, ord) < 0;
+        }
+
+        public override List<GroupCount> GetGroups()
+        {
+            return groups;
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                groupFieldTermIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                countFieldTermIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, countField);
+                ordSet.Clear();
+                foreach (GroupCount group in groups)
+                {
+                    int groupOrd = group.groupValue == null ? -1 : groupFieldTermIndex.LookupTerm(group.groupValue);
+                    if (group.groupValue != null && groupOrd < 0)
+                    {
+                        continue;
+                    }
+
+                    groupCounts[ordSet.Put(groupOrd)] = group;
+                    group.ords = new int[group.uniqueValues.Count];
+                    Arrays.Fill(group.ords, -2);
+                    int i = 0;
+                    foreach (BytesRef value2 in group.uniqueValues)
+                    {
+                        int countOrd = value2 == null ? -1 : countFieldTermIndex.LookupTerm(value2);
+                        if (value2 == null || countOrd >= 0)
+                        {
+                            group.ords[i++] = countOrd;
+                        }
+                    }
+                }
+            }
+        }
+
+        /** Holds distinct values for a single group.
+         *
+         * @lucene.experimental */
+        public class GroupCount : AbstractGroupCount<BytesRef> /*AbstractDistinctValuesCollector.GroupCount<BytesRef>*/
+        {
+            internal int[] ords;
+
+            internal GroupCount(BytesRef groupValue)
+                    : base(groupValue)
+            {
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
new file mode 100644
index 0000000..17003ba
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
@@ -0,0 +1,88 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+
+namespace Lucene.Net.Search.Grouping.Terms
+{
+    /// <summary>
+    /// Concrete implementation of <see cref="AbstractFirstPassGroupingCollector{BytesRef}"/> that groups based on
+    /// field values and more specifically uses <see cref="SortedDocValues"/>
+    /// to collect groups.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class TermFirstPassGroupingCollector : AbstractFirstPassGroupingCollector<BytesRef>
+    {
+        private readonly BytesRef scratchBytesRef = new BytesRef();
+        private SortedDocValues index;
+
+        private string groupField;
+
+        /// <summary>
+        /// Create the first pass collector.
+        /// </summary>
+        /// <param name="groupField">
+        /// The field used to group
+        /// documents. This field must be single-valued and
+        /// indexed (<see cref="FieldCache"/> is used to access its value
+        /// per-document).
+        /// </param>
+        /// <param name="groupSort">
+        /// The <see cref="Sort"/> used to sort the
+        /// groups.  The top sorted document within each group
+        /// according to groupSort, determines how that group
+        /// sorts against other groups.  This must be non-null,
+        /// ie, if you want to groupSort by relevance use
+        /// <see cref="Sort.RELEVANCE"/>.
+        /// </param>
+        /// <param name="topNGroups">
+        /// How many top groups to keep.
+        /// </param>
+        /// <exception cref="IOException">When I/O related errors occur</exception>
+        public TermFirstPassGroupingCollector(string groupField, Sort groupSort, int topNGroups)
+            : base(groupSort, topNGroups)
+        {
+            this.groupField = groupField;
+        }
+
+        protected override BytesRef GetDocGroupValue(int doc)
+        {
+            int ord = index.GetOrd(doc);
+            if (ord == -1)
+            {
+                return null;
+            }
+            else
+            {
+                index.LookupOrd(ord, scratchBytesRef);
+                return scratchBytesRef;
+            }
+        }
+
+        protected override BytesRef CopyDocGroupValue(BytesRef groupValue, BytesRef reuse)
+        {
+            if (groupValue == null)
+            {
+                return null;
+            }
+            else if (reuse != null)
+            {
+                reuse.CopyBytes(groupValue);
+                return reuse;
+            }
+            else
+            {
+                return BytesRef.DeepCopyOf(groupValue);
+            }
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                base.NextReader = value;
+                index = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs b/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
new file mode 100644
index 0000000..08fbb70
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
@@ -0,0 +1,444 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping.Terms
+{
+    /// <summary>
+    /// An implementation of <see cref="AbstractGroupFacetCollector"/> that computes grouped facets based on the indexed terms
+    /// from the <see cref="FieldCache"/>.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public abstract class TermGroupFacetCollector : AbstractGroupFacetCollector
+    {
+        internal readonly List<GroupedFacetHit> groupedFacetHits;
+        internal readonly SentinelIntSet segmentGroupedFacetHits;
+
+        internal SortedDocValues groupFieldTermsIndex;
+
+        /**
+         * Factory method for creating the right implementation based on the fact whether the facet field contains
+         * multiple tokens per documents.
+         *
+         * @param groupField The group field
+         * @param facetField The facet field
+         * @param facetFieldMultivalued Whether the facet field has multiple tokens per document
+         * @param facetPrefix The facet prefix a facet entry should start with to be included.
+         * @param initialSize The initial allocation size of the internal int set and group facet list which should roughly
+         *                    match the total number of expected unique groups. Be aware that the heap usage is
+         *                    4 bytes * initialSize.
+         * @return <code>TermGroupFacetCollector</code> implementation
+         */
+        public static TermGroupFacetCollector CreateTermGroupFacetCollector(string groupField,
+                                                                            string facetField,
+                                                                            bool facetFieldMultivalued,
+                                                                            BytesRef facetPrefix,
+                                                                            int initialSize)
+        {
+            if (facetFieldMultivalued)
+            {
+                return new MV(groupField, facetField, facetPrefix, initialSize);
+            }
+            else
+            {
+                return new SV(groupField, facetField, facetPrefix, initialSize);
+            }
+        }
+
+        internal TermGroupFacetCollector(string groupField, string facetField, BytesRef facetPrefix, int initialSize)
+            : base(groupField, facetField, facetPrefix)
+        {
+            groupedFacetHits = new List<GroupedFacetHit>(initialSize);
+            segmentGroupedFacetHits = new SentinelIntSet(initialSize, int.MinValue);
+        }
+
+        // Implementation for single valued facet fields.
+        internal class SV : TermGroupFacetCollector
+        {
+
+            private SortedDocValues facetFieldTermsIndex;
+
+            internal SV(string groupField, string facetField, BytesRef facetPrefix, int initialSize)
+                        : base(groupField, facetField, facetPrefix, initialSize)
+            {
+            }
+
+            public override void Collect(int doc)
+            {
+                int facetOrd = facetFieldTermsIndex.GetOrd(doc);
+                if (facetOrd < startFacetOrd || facetOrd >= endFacetOrd)
+                {
+                    return;
+                }
+
+                int groupOrd = groupFieldTermsIndex.GetOrd(doc);
+                int segmentGroupedFacetsIndex = groupOrd * (facetFieldTermsIndex.ValueCount + 1) + facetOrd;
+                if (segmentGroupedFacetHits.Exists(segmentGroupedFacetsIndex))
+                {
+                    return;
+                }
+
+                segmentTotalCount++;
+                segmentFacetCounts[facetOrd + 1]++;
+
+                segmentGroupedFacetHits.Put(segmentGroupedFacetsIndex);
+
+                BytesRef groupKey;
+                if (groupOrd == -1)
+                {
+                    groupKey = null;
+                }
+                else
+                {
+                    groupKey = new BytesRef();
+                    groupFieldTermsIndex.LookupOrd(groupOrd, groupKey);
+                }
+
+                BytesRef facetKey;
+                if (facetOrd == -1)
+                {
+                    facetKey = null;
+                }
+                else
+                {
+                    facetKey = new BytesRef();
+                    facetFieldTermsIndex.LookupOrd(facetOrd, facetKey);
+                }
+
+                groupedFacetHits.Add(new GroupedFacetHit(groupKey, facetKey));
+            }
+
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    if (segmentFacetCounts != null)
+                    {
+                        segmentResults.Add(CreateSegmentResult());
+                    }
+
+                    groupFieldTermsIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                    facetFieldTermsIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, facetField);
+
+                    // 1+ to allow for the -1 "not set":
+                    segmentFacetCounts = new int[facetFieldTermsIndex.ValueCount + 1];
+                    segmentTotalCount = 0;
+
+                    segmentGroupedFacetHits.Clear();
+                    foreach (GroupedFacetHit groupedFacetHit in groupedFacetHits)
+                    {
+                        int facetOrd = groupedFacetHit.facetValue == null ? -1 : facetFieldTermsIndex.LookupTerm(groupedFacetHit.facetValue);
+                        if (groupedFacetHit.facetValue != null && facetOrd < 0)
+                        {
+                            continue;
+                        }
+
+                        int groupOrd = groupedFacetHit.groupValue == null ? -1 : groupFieldTermsIndex.LookupTerm(groupedFacetHit.groupValue);
+                        if (groupedFacetHit.groupValue != null && groupOrd < 0)
+                        {
+                            continue;
+                        }
+
+                        int segmentGroupedFacetsIndex = groupOrd * (facetFieldTermsIndex.ValueCount + 1) + facetOrd;
+                        segmentGroupedFacetHits.Put(segmentGroupedFacetsIndex);
+                    }
+
+                    if (facetPrefix != null)
+                    {
+                        startFacetOrd = facetFieldTermsIndex.LookupTerm(facetPrefix);
+                        if (startFacetOrd < 0)
+                        {
+                            // Points to the ord one higher than facetPrefix
+                            startFacetOrd = -startFacetOrd - 1;
+                        }
+                        BytesRef facetEndPrefix = BytesRef.DeepCopyOf(facetPrefix);
+                        facetEndPrefix.Append(UnicodeUtil.BIG_TERM);
+                        endFacetOrd = facetFieldTermsIndex.LookupTerm(facetEndPrefix);
+                        Debug.Assert(endFacetOrd < 0);
+                        endFacetOrd = -endFacetOrd - 1; // Points to the ord one higher than facetEndPrefix
+                    }
+                    else
+                    {
+                        startFacetOrd = -1;
+                        endFacetOrd = facetFieldTermsIndex.ValueCount;
+                    }
+                }
+            }
+
+
+            protected override AbstractSegmentResult CreateSegmentResult()
+            {
+                return new SegmentResult(segmentFacetCounts, segmentTotalCount, facetFieldTermsIndex.TermsEnum(), startFacetOrd, endFacetOrd);
+            }
+
+            internal class SegmentResult : AbstractGroupFacetCollector.AbstractSegmentResult
+            {
+
+                internal readonly TermsEnum tenum;
+
+                internal SegmentResult(int[] counts, int total, TermsEnum tenum, int startFacetOrd, int endFacetOrd)
+                                : base(counts, total - counts[0], counts[0], endFacetOrd + 1)
+                {
+                    this.tenum = tenum;
+                    this.mergePos = startFacetOrd == -1 ? 1 : startFacetOrd + 1;
+                    if (mergePos < maxTermPos)
+                    {
+                        Debug.Assert(tenum != null);
+                        tenum.SeekExact(startFacetOrd == -1 ? 0 : startFacetOrd);
+                        mergeTerm = tenum.Term();
+                    }
+                }
+
+                protected internal override void NextTerm()
+                {
+                    mergeTerm = tenum.Next();
+                }
+            }
+        }
+
+        // Implementation for multi valued facet fields.
+        internal class MV : TermGroupFacetCollector
+        {
+
+            private SortedSetDocValues facetFieldDocTermOrds;
+            private TermsEnum facetOrdTermsEnum;
+            private int facetFieldNumTerms;
+            private readonly BytesRef scratch = new BytesRef();
+
+            internal MV(string groupField, string facetField, BytesRef facetPrefix, int initialSize)
+                         : base(groupField, facetField, facetPrefix, initialSize)
+            {
+            }
+
+            public override void Collect(int doc)
+            {
+                int groupOrd = groupFieldTermsIndex.GetOrd(doc);
+                if (facetFieldNumTerms == 0)
+                {
+                    int segmentGroupedFacetsIndex = groupOrd * (facetFieldNumTerms + 1);
+                    if (facetPrefix != null || segmentGroupedFacetHits.Exists(segmentGroupedFacetsIndex))
+                    {
+                        return;
+                    }
+
+                    segmentTotalCount++;
+                    segmentFacetCounts[facetFieldNumTerms]++;
+
+                    segmentGroupedFacetHits.Put(segmentGroupedFacetsIndex);
+                    BytesRef groupKey;
+                    if (groupOrd == -1)
+                    {
+                        groupKey = null;
+                    }
+                    else
+                    {
+                        groupKey = new BytesRef();
+                        groupFieldTermsIndex.LookupOrd(groupOrd, groupKey);
+                    }
+                    groupedFacetHits.Add(new GroupedFacetHit(groupKey, null));
+                    return;
+                }
+
+                facetFieldDocTermOrds.Document = doc;
+                long ord;
+                bool empty = true;
+                while ((ord = facetFieldDocTermOrds.NextOrd()) != SortedSetDocValues.NO_MORE_ORDS)
+                {
+                    Process(groupOrd, (int)ord);
+                    empty = false;
+                }
+
+                if (empty)
+                {
+                    Process(groupOrd, facetFieldNumTerms); // this facet ord is reserved for docs not containing facet field.
+                }
+            }
+
+            private void Process(int groupOrd, int facetOrd)
+            {
+                if (facetOrd < startFacetOrd || facetOrd >= endFacetOrd)
+                {
+                    return;
+                }
+
+                int segmentGroupedFacetsIndex = groupOrd * (facetFieldNumTerms + 1) + facetOrd;
+                if (segmentGroupedFacetHits.Exists(segmentGroupedFacetsIndex))
+                {
+                    return;
+                }
+
+                segmentTotalCount++;
+                segmentFacetCounts[facetOrd]++;
+
+                segmentGroupedFacetHits.Put(segmentGroupedFacetsIndex);
+
+                BytesRef groupKey;
+                if (groupOrd == -1)
+                {
+                    groupKey = null;
+                }
+                else
+                {
+                    groupKey = new BytesRef();
+                    groupFieldTermsIndex.LookupOrd(groupOrd, groupKey);
+                }
+
+                BytesRef facetValue;
+                if (facetOrd == facetFieldNumTerms)
+                {
+                    facetValue = null;
+                }
+                else
+                {
+                    facetFieldDocTermOrds.LookupOrd(facetOrd, scratch);
+                    facetValue = BytesRef.DeepCopyOf(scratch); // must we?
+                }
+                groupedFacetHits.Add(new GroupedFacetHit(groupKey, facetValue));
+            }
+
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    if (segmentFacetCounts != null)
+                    {
+                        segmentResults.Add(CreateSegmentResult());
+                    }
+
+                    groupFieldTermsIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                    facetFieldDocTermOrds = FieldCache.DEFAULT.GetDocTermOrds(value.AtomicReader, facetField);
+                    facetFieldNumTerms = (int)facetFieldDocTermOrds.ValueCount;
+                    if (facetFieldNumTerms == 0)
+                    {
+                        facetOrdTermsEnum = null;
+                    }
+                    else
+                    {
+                        facetOrdTermsEnum = facetFieldDocTermOrds.TermsEnum();
+                    }
+                    // [facetFieldNumTerms() + 1] for all possible facet values and docs not containing facet field
+                    segmentFacetCounts = new int[facetFieldNumTerms + 1];
+                    segmentTotalCount = 0;
+
+                    segmentGroupedFacetHits.Clear();
+                    foreach (GroupedFacetHit groupedFacetHit in groupedFacetHits)
+                    {
+                        int groupOrd = groupedFacetHit.groupValue == null ? -1 : groupFieldTermsIndex.LookupTerm(groupedFacetHit.groupValue);
+                        if (groupedFacetHit.groupValue != null && groupOrd < 0)
+                        {
+                            continue;
+                        }
+
+                        int facetOrd;
+                        if (groupedFacetHit.facetValue != null)
+                        {
+                            if (facetOrdTermsEnum == null || !facetOrdTermsEnum.SeekExact(groupedFacetHit.facetValue))
+                            {
+                                continue;
+                            }
+                            facetOrd = (int)facetOrdTermsEnum.Ord();
+                        }
+                        else
+                        {
+                            facetOrd = facetFieldNumTerms;
+                        }
+
+                        // (facetFieldDocTermOrds.numTerms() + 1) for all possible facet values and docs not containing facet field
+                        int segmentGroupedFacetsIndex = groupOrd * (facetFieldNumTerms + 1) + facetOrd;
+                        segmentGroupedFacetHits.Put(segmentGroupedFacetsIndex);
+                    }
+
+                    if (facetPrefix != null)
+                    {
+                        TermsEnum.SeekStatus seekStatus;
+                        if (facetOrdTermsEnum != null)
+                        {
+                            seekStatus = facetOrdTermsEnum.SeekCeil(facetPrefix);
+                        }
+                        else
+                        {
+                            seekStatus = TermsEnum.SeekStatus.END;
+                        }
+
+                        if (seekStatus != TermsEnum.SeekStatus.END)
+                        {
+                            startFacetOrd = (int)facetOrdTermsEnum.Ord();
+                        }
+                        else
+                        {
+                            startFacetOrd = 0;
+                            endFacetOrd = 0;
+                            return;
+                        }
+
+                        BytesRef facetEndPrefix = BytesRef.DeepCopyOf(facetPrefix);
+                        facetEndPrefix.Append(UnicodeUtil.BIG_TERM);
+                        seekStatus = facetOrdTermsEnum.SeekCeil(facetEndPrefix);
+                        if (seekStatus != TermsEnum.SeekStatus.END)
+                        {
+                            endFacetOrd = (int)facetOrdTermsEnum.Ord();
+                        }
+                        else
+                        {
+                            endFacetOrd = facetFieldNumTerms; // Don't include null...
+                        }
+                    }
+                    else
+                    {
+                        startFacetOrd = 0;
+                        endFacetOrd = facetFieldNumTerms + 1;
+                    }
+                }
+            }
+
+            protected override AbstractSegmentResult CreateSegmentResult()
+            {
+                return new SegmentResult(segmentFacetCounts, segmentTotalCount, facetFieldNumTerms, facetOrdTermsEnum, startFacetOrd, endFacetOrd);
+            }
+
+            internal class SegmentResult : AbstractGroupFacetCollector.AbstractSegmentResult
+            {
+
+                internal readonly TermsEnum tenum;
+
+                internal SegmentResult(int[] counts, int total, int missingCountIndex, TermsEnum tenum, int startFacetOrd, int endFacetOrd)
+                                : base(counts, total - counts[missingCountIndex], counts[missingCountIndex],
+                        endFacetOrd == missingCountIndex + 1 ? missingCountIndex : endFacetOrd)
+                {
+                    this.tenum = tenum;
+                    this.mergePos = startFacetOrd;
+                    if (tenum != null)
+                    {
+                        tenum.SeekExact(mergePos);
+                        mergeTerm = tenum.Term();
+                    }
+                }
+
+                protected internal override void NextTerm()
+                {
+                    mergeTerm = tenum.Next();
+                }
+            }
+        }
+    }
+
+
+    internal class GroupedFacetHit
+    {
+        internal readonly BytesRef groupValue;
+        internal readonly BytesRef facetValue;
+
+        internal GroupedFacetHit(BytesRef groupValue, BytesRef facetValue)
+        {
+            this.groupValue = groupValue;
+            this.facetValue = facetValue;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
new file mode 100644
index 0000000..da70372
--- /dev/null
+++ b/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
@@ -0,0 +1,65 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping.Terms
+{
+    /// <summary>
+    /// Concrete implementation of <see cref="AbstractSecondPassGroupingCollector{BytesRef}"/> that groups based on
+    /// field values and more specifically uses <see cref="SortedDocValues"/>
+    /// to collect grouped docs.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    public class TermSecondPassGroupingCollector : AbstractSecondPassGroupingCollector<BytesRef>
+    {
+        private readonly SentinelIntSet ordSet;
+        private SortedDocValues index;
+        private readonly string groupField;
+
+        public TermSecondPassGroupingCollector(string groupField, ICollection<SearchGroup<BytesRef>> groups, Sort groupSort, Sort withinGroupSort,
+                                               int maxDocsPerGroup, bool getScores, bool getMaxScores, bool fillSortFields)
+                  : base(groups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields)
+        {
+            ordSet = new SentinelIntSet(groupMap.Count, -2);
+            this.groupField = groupField;
+            groupDocs = /*(SearchGroupDocs<BytesRef>[])*/ new AbstractSecondPassGroupingCollector.SearchGroupDocs<BytesRef>[ordSet.Keys.Length];
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                base.NextReader = value;
+                index = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+
+                // Rebuild ordSet
+                ordSet.Clear();
+                foreach (AbstractSecondPassGroupingCollector.SearchGroupDocs<BytesRef> group in groupMap.Values)
+                {
+                    //      System.out.println("  group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
+                    int ord = group.groupValue == null ? -1 : index.LookupTerm(group.groupValue);
+                    if (group.groupValue == null || ord >= 0)
+                    {
+                        groupDocs[ordSet.Put(ord)] = group;
+                    }
+                }
+            }
+        }
+
+        protected override AbstractSecondPassGroupingCollector.SearchGroupDocs<BytesRef> RetrieveGroup(int doc)
+        {
+            int slot = ordSet.Find(index.GetOrd(doc));
+            if (slot >= 0)
+            {
+                return groupDocs[slot];
+            }
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Grouping/TopGroups.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/TopGroups.cs b/src/Lucene.Net.Grouping/TopGroups.cs
index 017c975..091103d 100644
--- a/src/Lucene.Net.Grouping/TopGroups.cs
+++ b/src/Lucene.Net.Grouping/TopGroups.cs
@@ -1,7 +1,6 @@
 \ufeffusing System;
-using Lucene.Net.Search;
 
-namespace Lucene.Net.Grouping
+namespace Lucene.Net.Search.Grouping
 {
     /*
 	 * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -25,7 +24,7 @@ namespace Lucene.Net.Grouping
     /// 
     /// @lucene.experimental 
     /// </summary>
-    public class TopGroups<TGroupValueType>
+    public class TopGroups<TGroupValue>
     {
         /// <summary>
         /// Number of documents matching the search </summary>
@@ -41,7 +40,7 @@ namespace Lucene.Net.Grouping
 
         /// <summary>
         /// Group results in groupSort order </summary>
-        public readonly GroupDocs<TGroupValueType>[] Groups;
+        public readonly GroupDocs<TGroupValue>[] Groups;
 
         /// <summary>
         /// How groups are sorted against each other </summary>
@@ -57,7 +56,7 @@ namespace Lucene.Net.Grouping
         /// </summary>
         public readonly float MaxScore;
 
-        public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<TGroupValueType>[] groups, float maxScore)
+        public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<TGroupValue>[] groups, float maxScore)
         {
             GroupSort = groupSort;
             WithinGroupSort = withinGroupSort;
@@ -68,7 +67,7 @@ namespace Lucene.Net.Grouping
             MaxScore = maxScore;
         }
 
-        public TopGroups(TopGroups<TGroupValueType> oldTopGroups, int? totalGroupCount)
+        public TopGroups(TopGroups<TGroupValue> oldTopGroups, int? totalGroupCount)
         {
             GroupSort = oldTopGroups.GroupSort;
             WithinGroupSort = oldTopGroups.WithinGroupSort;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
new file mode 100644
index 0000000..4cc29e3
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
@@ -0,0 +1,30 @@
+\ufeffusing Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    /// <summary>
+    /// Base class for grouping related tests.
+    /// </summary>
+    // TODO (MvG) : The grouping tests contain a lot of code duplication. Try to move the common code to this class..
+    public abstract class AbstractGroupingTestCase : LuceneTestCase
+    {
+        protected string GenerateRandomNonEmptyString()
+        {
+            string randomValue;
+            do
+            {
+                // B/c of DV based impl we can't see the difference between an empty string and a null value.
+                // For that reason we don't generate empty string
+                // groups.
+                randomValue = TestUtil.RandomRealisticUnicodeString(Random());
+                //randomValue = TestUtil.randomSimpleString(random());
+            } while ("".equals(randomValue));
+            return randomValue;
+        }
+    }
+}


[49/58] [abbrv] lucenenet git commit: Grouping: Removed commented code.

Posted by ni...@apache.org.
Grouping: Removed commented code.


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

Branch: refs/heads/grouping
Commit: dd24cf3a0e30c963393939a1b5ba45e009c709d0
Parents: 41b9732
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 23:15:52 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:01 2016 +0700

----------------------------------------------------------------------
 .../AbstractAllGroupHeadsCollector.cs           | 29 +-----------
 .../AbstractAllGroupsCollector.cs               | 28 -----------
 .../AbstractFirstPassGroupingCollector.cs       | 20 --------
 .../AbstractGroupFacetCollector.cs              | 25 ----------
 .../AbstractSecondPassGroupingCollector.cs      |  4 +-
 src/Lucene.Net.Grouping/CollectedSearchGroup.cs |  2 +-
 .../Function/FunctionAllGroupHeadsCollector.cs  |  5 +-
 .../Term/TermAllGroupHeadsCollector.cs          |  5 +-
 .../AllGroupHeadsCollectorTest.cs               | 50 --------------------
 .../AllGroupsCollectorTest.cs                   |  1 -
 .../GroupFacetCollectorTest.cs                  | 49 ++-----------------
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs   | 48 -------------------
 12 files changed, 13 insertions(+), 253 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
index 5668b19..4d3b66f 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -151,8 +151,8 @@ namespace Lucene.Net.Search.Grouping
     /// </summary>
     /// <remarks>
     /// LUCENENET: moved this class from of the <see cref="AbstractAllGroupHeadsCollector{TGroupValue}"/>,
-    /// to <see cref="AbstractAllGroupHeadsCollector"/>, made it non-generic so the generic closing type doesn't need 
-    /// to be specified in classes that use <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> as a generic closing type, and renamed 
+    /// made it non-generic so the generic closing type doesn't need to be specified in classes that
+    /// use <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> as a generic closing type, and renamed 
     /// it from GroupHead to <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> to avoid naming conflicts with nested classes 
     /// named GroupHead in derived classes of <see cref="AbstractAllGroupHeadsCollector"/>.
     /// </remarks>
@@ -226,29 +226,4 @@ namespace Lucene.Net.Search.Grouping
         /// <exception cref="IOException">If I/O related errors occur</exception>
         protected abstract void RetrieveGroupHeadAndAddIfNotExist(int doc);
     }
-
-    ///// <summary>
-    ///// LUCENENET specific interface used to apply covariance to GH
-    ///// </summary>
-    //public interface IAbstractAllGroupHeadsCollector<out GH>
-    //{
-    //    /// <summary>
-    //    /// 
-    //    /// </summary>
-    //    /// <param name="maxDoc">The maxDoc of the top level <see cref="Index.IndexReader"/></param>
-    //    /// <returns>a <see cref="FixedBitSet"/> containing all group heads.</returns>
-    //    FixedBitSet RetrieveGroupHeads(int maxDoc);
-
-    //    /// <summary>
-    //    /// 
-    //    /// </summary>
-    //    /// <returns>an int array containing all group heads. The size of the array is equal to number of collected unique groups.</returns>
-    //    int[] RetrieveGroupHeads();
-
-    //    /// <summary>
-    //    /// 
-    //    /// </summary>
-    //    /// <returns>the number of group heads found for a query.</returns>
-    //    int GroupHeadsSize { get; }
-    //}
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
index df240ee..6f1edb4 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
@@ -79,32 +79,4 @@ namespace Lucene.Net.Search.Grouping
         /// <returns>the group values</returns>
         IEnumerable<TGroupValue> Groups { get; }
     }
-
-    ///// <summary>
-    ///// LUCENENET specific class used to reference <see cref="AbstractAllGroupsCollector{TGroupValue}"/>
-    ///// without refering to its generic closing type.
-    ///// </summary>
-    //public abstract class AbstractAllGroupsCollector : Collector
-    //{
-    //    /// <summary>
-    //    /// Returns the total number of groups for the executed search.
-    //    /// This is a convenience method. The following code snippet has the same effect: <code>GetGroups().Count</code>
-    //    /// </summary>
-    //    /// <returns>The total number of groups for the executed search</returns>
-    //    public abstract int GroupCount { get; }
-
-
-    //    // Empty not necessary
-    //    public override Scorer Scorer
-    //    {
-    //        set
-    //        {
-    //        }
-    //    }
-
-    //    public override bool AcceptsDocsOutOfOrder()
-    //    {
-    //        return true;
-    //    }
-    //}
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
index c7f6e52..aae0591 100644
--- a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
@@ -357,26 +357,6 @@ namespace Lucene.Net.Search.Grouping
         private void BuildSortedSet()
         {
             var comparator = new BuildSortedSetComparer(this);
-            //        var comparator = new Comparator<CollectedSearchGroup<?>>() {
-            //      @Override
-            //      public int compare(CollectedSearchGroup<?> o1, CollectedSearchGroup<?> o2)
-            //{
-            //    for (int compIDX = 0; ; compIDX++)
-            //    {
-            //        FieldComparator <?> fc = comparators[compIDX];
-            //        final int c = reversed[compIDX] * fc.compare(o1.comparatorSlot, o2.comparatorSlot);
-            //        if (c != 0)
-            //        {
-            //            return c;
-            //        }
-            //        else if (compIDX == compIDXEnd)
-            //        {
-            //            return o1.topDoc - o2.topDoc;
-            //        }
-            //    }
-            //}
-            //    };
-
             orderedGroups = new SortedSet<CollectedSearchGroup<TGroupValue>>(comparator);
             orderedGroups.UnionWith(groupMap.Values);
             Debug.Assert(orderedGroups.Count > 0);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
index 9769871..920e6d3 100644
--- a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
@@ -137,33 +137,8 @@ namespace Lucene.Net.Search.Grouping
         public class GroupedFacetResult
         {
             private readonly static IComparer<FacetEntry> orderByCountAndValue = new OrderByCountAndValueComparer();
-            //    private readonly static IComparer<FacetEntry> orderByCountAndValue = new Comparator<FacetEntry>() {
-
-            //      @Override
-            //      public override int Compare(FacetEntry a, FacetEntry b)
-            //    {
-            //        int cmp = b.count - a.count; // Highest count first!
-            //        if (cmp != 0)
-            //        {
-            //            return cmp;
-            //        }
-            //        return a.value.compareTo(b.value);
-            //    }
-
-            //};
-
             private readonly static IComparer<FacetEntry> orderByValue = new OrderByValueComparer();
 
-            //            private readonly static IComparer<FacetEntry> orderByValue = new Comparator<FacetEntry>() {
-
-            //      @Override
-            //      public int compare(FacetEntry a, FacetEntry b)
-            //{
-            //    return a.value.compareTo(b.value);
-            //}
-
-            //    };
-
             private readonly int maxSize;
             private readonly TreeSet<FacetEntry> facetEntries;
             private readonly int totalMissingCount;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
index 6364d90..de3feb6 100644
--- a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
@@ -50,7 +50,6 @@ namespace Lucene.Net.Search.Grouping
             foreach (SearchGroup<TGroupValue> group in groups)
             {
                 //System.out.println("  prep group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
-                //TopDocsCollector collector;
                 ITopDocsCollector collector;
                 if (withinGroupSort == null)
                 {
@@ -156,9 +155,8 @@ namespace Lucene.Net.Search.Grouping
         public class SearchGroupDocs<TGroupValue>
         {
             public readonly TGroupValue groupValue;
-            //public readonly TopDocsCollector<?> collector;
             public readonly ITopDocsCollector collector;
-            public SearchGroupDocs(TGroupValue groupValue, ITopDocsCollector /*TopDocsCollector<?>*/ collector)
+            public SearchGroupDocs(TGroupValue groupValue, ITopDocsCollector collector)
             {
                 this.groupValue = groupValue;
                 this.collector = collector;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
index 9ed6cb8..50b5bd7 100644
--- a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
+++ b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
@@ -21,7 +21,7 @@ namespace Lucene.Net.Search.Grouping
 
     /// <summary>
     /// LUCENENET specific interface for passing/comparing the CollectedSearchGroup
-    /// without referencing its generic type
+    /// without referencing its generic closing type
     /// </summary>
     public interface ICollectedSearchGroup
     {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
index 9b7f0cd..f0410d2 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
@@ -111,15 +111,16 @@ namespace Lucene.Net.Search.Grouping.Function
         /** Holds current head document for a single group.
          *
          * @lucene.experimental */
-        public class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<MutableValue>*/
+        public class GroupHead : AbstractAllGroupHeadsCollector_GroupHead
         {
 
             private readonly FunctionAllGroupHeadsCollector outerInstance;
+            // LUCENENET: Moved this here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
+            // need to reference the generic closing type MutableValue.
             public readonly MutableValue groupValue;
             internal readonly FieldComparator[] comparators;
 
             internal GroupHead(FunctionAllGroupHeadsCollector outerInstance, MutableValue groupValue, Sort sort, int doc)
-                        /*: base(groupValue, doc + outerInstance.readerContext.DocBase)*/
                         : base(doc + outerInstance.readerContext.DocBase)
             {
                 this.outerInstance = outerInstance;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
index 054dacc..4aa9615 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
@@ -757,9 +757,11 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+        internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead
         {
             private readonly ScoreAllGroupHeadsCollector outerInstance;
+            // LUCENENET: Moved this here from the base class, AbstractAllGroupHeadsCollector_GroupHead so it doesn't
+            // need to reference the generic closing type BytesRef.
             public readonly BytesRef groupValue;
             internal float[] scores;
 
@@ -800,7 +802,6 @@ namespace Lucene.Net.Search.Grouping.Terms
                 }
                 this.Doc = doc + outerInstance.readerContext.DocBase;
             }
-
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index 6b7c06a..2d8e8fe 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -488,7 +488,6 @@ namespace Lucene.Net.Search.Grouping
             {
                 List<GroupDoc> docs = groupHeads[groupValue];
                 docs.Sort(GetComparator(docSort, sortByScoreOnly, fieldIdToDocID));
-                //Collections.Sort(docs, getComparator(docSort, sortByScoreOnly, fieldIdToDocID));
                 allGroupHeads[i++] = docs[0].id;
             }
 
@@ -600,55 +599,6 @@ namespace Lucene.Net.Search.Grouping
         {
             SortField[] sortFields = sort.GetSort();
             return new ComparatorAnonymousHelper(this, sortFields, sortByScoreOnly, fieldIdToDocID);
-            //    return new Comparator<GroupDoc>() {
-            //      @Override
-            //      public int compare(GroupDoc d1, GroupDoc d2)
-            //{
-            //    for (SortField sf : sortFields)
-            //    {
-            //        final int cmp;
-            //        if (sf.getType() == SortField.Type.SCORE)
-            //        {
-            //            if (d1.score > d2.score)
-            //            {
-            //                cmp = -1;
-            //            }
-            //            else if (d1.score < d2.score)
-            //            {
-            //                cmp = 1;
-            //            }
-            //            else
-            //            {
-            //                cmp = sortByScoreOnly ? fieldIdToDocID[d1.id] - fieldIdToDocID[d2.id] : 0;
-            //            }
-            //        }
-            //        else if (sf.getField().equals("sort1"))
-            //        {
-            //            cmp = d1.sort1.compareTo(d2.sort1);
-            //        }
-            //        else if (sf.getField().equals("sort2"))
-            //        {
-            //            cmp = d1.sort2.compareTo(d2.sort2);
-            //        }
-            //        else if (sf.getField().equals("sort3"))
-            //        {
-            //            cmp = d1.sort3.compareTo(d2.sort3);
-            //        }
-            //        else
-            //        {
-            //            assertEquals(sf.getField(), "id");
-            //            cmp = d1.id - d2.id;
-            //        }
-            //        if (cmp != 0)
-            //        {
-            //            return sf.getReverse() ? -cmp : cmp;
-            //        }
-            //    }
-            //    // Our sort always fully tie breaks:
-            //    fail();
-            //    return 0;
-            //}
-            //    };
         }
 
         private AbstractAllGroupHeadsCollector CreateRandomCollector(string groupField, Sort sortWithinGroup, bool canUseIDV, DocValuesType_e valueType)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
index 681c644..1efd4b5 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
@@ -139,6 +139,5 @@ namespace Lucene.Net.Search.Grouping
 
             return selected;
         }
-
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
index a8f191d..dda2cdb 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
@@ -586,31 +586,10 @@ namespace Lucene.Net.Search.Grouping
             docNoFacet.Add(content);
             docNoGroupNoFacet.Add(content);
 
+            // LUCENENET NOTE: TreeSet (the class used in Java) allows duplicate keys. However, SortedSet seems to work,
+            // and based on the name of the variable, presuming the keys are meant to be unique.
             ISet<string> uniqueFacetValues = new SortedSet<string>(new ComparerAnonymousHelper1());
-            //    ISet<string> uniqueFacetValues = new SortedSet<string>(new Comparator<String>() {
-
-            //      @Override
-            //      public int compare(String a, String b)
-            //{
-            //    if (a == b)
-            //    {
-            //        return 0;
-            //    }
-            //    else if (a == null)
-            //    {
-            //        return -1;
-            //    }
-            //    else if (b == null)
-            //    {
-            //        return 1;
-            //    }
-            //    else
-            //    {
-            //        return a.compareTo(b);
-            //    }
-            //}
-
-            //    });
+
             // LUCENENET NOTE: Need HashMap here because of null keys
             IDictionary<string, HashMap<string, ISet<string>>> searchTermToFacetToGroups = new Dictionary<string, HashMap<string, ISet<string>>>();
             int facetWithMostGroups = 0;
@@ -767,8 +746,6 @@ namespace Lucene.Net.Search.Grouping
 
         private GroupedFacetResult CreateExpectedFacetResult(string searchTerm, IndexContext context, int offset, int limit, int minCount, bool orderByCount, string facetPrefix)
         {
-            //IDictionary<string, ISet<string>> facetGroups = context.searchTermToFacetGroups.get(searchTerm);
-            //if (facetGroups == null)
             HashMap<string, ISet<string>> facetGroups;
             if (!context.searchTermToFacetGroups.TryGetValue(searchTerm, out facetGroups))
             {
@@ -824,24 +801,6 @@ namespace Lucene.Net.Search.Grouping
 
             entries.Sort(new ComparerAnonymousHelper2(orderByCount));
 
-            //    Collections.sort(entries, new Comparator<TermGroupFacetCollector.FacetEntry>() {
-
-            //      @Override
-            //      public int compare(TermGroupFacetCollector.FacetEntry a, TermGroupFacetCollector.FacetEntry b)
-            //{
-            //    if (orderByCount)
-            //    {
-            //        int cmp = b.getCount() - a.getCount();
-            //        if (cmp != 0)
-            //        {
-            //            return cmp;
-            //        }
-            //    }
-            //    return a.getValue().compareTo(b.getValue());
-            //}
-
-            //    });
-
             int endOffset = offset + limit;
             List<TermGroupFacetCollector.FacetEntry> entriesResult;
             if (offset >= entries.size())
@@ -850,12 +809,10 @@ namespace Lucene.Net.Search.Grouping
             }
             else if (endOffset >= entries.size())
             {
-                //entriesResult = (List<TermGroupFacetCollector.FacetEntry>)entries.SubList(offset, entries.size());
                 entriesResult = entries.GetRange(offset, entries.size() - offset);
             }
             else
             {
-                //entriesResult = (List<TermGroupFacetCollector.FacetEntry>)entries.SubList(offset, endOffset);
                 entriesResult = entries.GetRange(offset, endOffset - offset);
             }
             return new GroupedFacetResult(totalCount, totalMissCount, entriesResult);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dd24cf3a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index 2291a74..ddef166 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -480,51 +480,6 @@ namespace Lucene.Net.Search.Grouping
         {
             SortField[] sortFields = sort.GetSort();
             return new ComparerAnonymousHelper(this, sortFields);
-            //    return new Comparator<GroupDoc>() {
-            //      @Override
-            //      public int compare(GroupDoc d1, GroupDoc d2)
-            //{
-            //    for (SortField sf : sortFields)
-            //    {
-            //        final int cmp;
-            //        if (sf.getType() == SortField.Type.SCORE)
-            //        {
-            //            if (d1.score > d2.score)
-            //            {
-            //                cmp = -1;
-            //            }
-            //            else if (d1.score < d2.score)
-            //            {
-            //                cmp = 1;
-            //            }
-            //            else
-            //            {
-            //                cmp = 0;
-            //            }
-            //        }
-            //        else if (sf.getField().equals("sort1"))
-            //        {
-            //            cmp = d1.sort1.compareTo(d2.sort1);
-            //        }
-            //        else if (sf.getField().equals("sort2"))
-            //        {
-            //            cmp = d1.sort2.compareTo(d2.sort2);
-            //        }
-            //        else
-            //        {
-            //            assertEquals(sf.getField(), "id");
-            //            cmp = d1.id - d2.id;
-            //        }
-            //        if (cmp != 0)
-            //        {
-            //            return sf.getReverse() ? -cmp : cmp;
-            //        }
-            //    }
-            //    // Our sort always fully tie breaks:
-            //    fail();
-            //    return 0;
-            //}
-            //    };
         }
 
         private IComparable[] FillFields(GroupDoc d, Sort sort)
@@ -645,7 +600,6 @@ namespace Lucene.Net.Search.Grouping
                 BytesRef group = sortedGroups[idx];
                 List<GroupDoc> docs = groups[group];
                 totalGroupedHitCount += docs.size();
-                //Collections.sort(docs, docSortComp);
                 docs.Sort(docSortComp);
                 ScoreDoc[] hits;
                 if (docs.size() > docOffset)
@@ -696,7 +650,6 @@ namespace Lucene.Net.Search.Grouping
         private DirectoryReader GetDocBlockReader(Directory dir, GroupDoc[] groupDocs)
         {
             // Coalesce by group, but in random order:
-            //Collections.shuffle(Arrays.asList(groupDocs), Random());
             groupDocs = CollectionsHelper.Shuffle(Arrays.AsList(groupDocs)).ToArray();
             HashMap<BytesRef, List<GroupDoc>> groupMap = new HashMap<BytesRef, List<GroupDoc>>();
             List<BytesRef> groupValues = new List<BytesRef>();
@@ -1710,7 +1663,6 @@ namespace Lucene.Net.Search.Grouping
             public ShardSearcher(AtomicReaderContext ctx, IndexReaderContext parent)
                             : base(parent)
             {
-                //this.ctx = Collections.SingletonList(ctx);
                 this.ctx = new List<AtomicReaderContext>(new AtomicReaderContext[] { ctx });
             }
 


[48/58] [abbrv] lucenenet git commit: Renamed AbstractGroupHead to AbstractAllGroupHeadsCollector_GroupHead so it is similar to its original name, AbstractAllGroupHeadsCollector.GroupHead. Due to conflicts with other classes named GroupHead in derived cl

Posted by ni...@apache.org.
Renamed AbstractGroupHead to AbstractAllGroupHeadsCollector_GroupHead so it is similar to its original name, AbstractAllGroupHeadsCollector.GroupHead. Due to conflicts with other classes named GroupHead in derived classes of AbstractAllGroupHeadsCollector, the original name could not be used.


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

Branch: refs/heads/grouping
Commit: 95bb669287a986c676b6e4ecf5f95d48341cacf1
Parents: 840c67b
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 21:47:59 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:58 2016 +0700

----------------------------------------------------------------------
 .../AbstractAllGroupHeadsCollector.cs           |  13 +-
 .../Function/FunctionAllGroupHeadsCollector.cs  |   2 +-
 .../Term/TermAllGroupHeadsCollector.cs          | 993 +++++++++----------
 3 files changed, 505 insertions(+), 503 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/95bb6692/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
index f27d2e4..5668b19 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
 namespace Lucene.Net.Search.Grouping
 {
     public abstract class AbstractAllGroupHeadsCollector<GH> : AbstractAllGroupHeadsCollector
-        where GH : AbstractGroupHead /*AbstractAllGroupHeadsCollector<GH>.GroupHead*/
+        where GH : AbstractAllGroupHeadsCollector_GroupHead
     {
         protected readonly int[] reversed;
         protected readonly int compIDXEnd;
@@ -150,16 +150,19 @@ namespace Lucene.Net.Search.Grouping
     /// </para>
     /// </summary>
     /// <remarks>
-    /// LUCENENET: moved this class outside of the AbstractAllGroupHeadsCollector,
-    /// made non-generic, and renamed from GroupHead to AbstractGroupHead.
+    /// LUCENENET: moved this class from of the <see cref="AbstractAllGroupHeadsCollector{TGroupValue}"/>,
+    /// to <see cref="AbstractAllGroupHeadsCollector"/>, made it non-generic so the generic closing type doesn't need 
+    /// to be specified in classes that use <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> as a generic closing type, and renamed 
+    /// it from GroupHead to <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> to avoid naming conflicts with nested classes 
+    /// named GroupHead in derived classes of <see cref="AbstractAllGroupHeadsCollector"/>.
     /// </remarks>
-    public abstract class AbstractGroupHead /*<TGroupValue>*/
+    public abstract class AbstractAllGroupHeadsCollector_GroupHead /*<TGroupValue>*/
     {
 
         //public readonly TGroupValue groupValue;
         public int Doc { get; protected set; }
 
-        protected AbstractGroupHead(/*TGroupValue groupValue,*/ int doc)
+        protected AbstractAllGroupHeadsCollector_GroupHead(/*TGroupValue groupValue,*/ int doc)
         {
             //this.groupValue = groupValue;
             this.Doc = doc;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/95bb6692/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
index c50219d..9b7f0cd 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
@@ -111,7 +111,7 @@ namespace Lucene.Net.Search.Grouping.Function
         /** Holds current head document for a single group.
          *
          * @lucene.experimental */
-        public class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<MutableValue>*/
+        public class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<MutableValue>*/
         {
 
             private readonly FunctionAllGroupHeadsCollector outerInstance;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/95bb6692/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
index fbbec34..054dacc 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
@@ -18,7 +18,8 @@ namespace Lucene.Net.Search.Grouping.Terms
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="GH"></typeparam>
-    public abstract class TermAllGroupHeadsCollector<GH> : AbstractAllGroupHeadsCollector<GH> where GH : AbstractGroupHead /*AbstractAllGroupHeadsCollector<GH>.GroupHead*/
+    public abstract class TermAllGroupHeadsCollector<GH> : AbstractAllGroupHeadsCollector<GH>
+        where GH : AbstractAllGroupHeadsCollector_GroupHead
     {
         internal readonly string groupField;
         internal readonly BytesRef scratchBytesRef = new BytesRef();
@@ -112,696 +113,694 @@ namespace Lucene.Net.Search.Grouping.Terms
 
     // A general impl that works for any group sort.
     internal class GeneralAllGroupHeadsCollector : TermAllGroupHeadsCollector<GeneralAllGroupHeadsCollector.GroupHead>
-        {
+    {
 
-            private readonly Sort sortWithinGroup;
-            private readonly IDictionary<BytesRef, GroupHead> groups;
+        private readonly Sort sortWithinGroup;
+        private readonly IDictionary<BytesRef, GroupHead> groups;
 
-            internal Scorer scorer;
+        internal Scorer scorer;
 
-            internal GeneralAllGroupHeadsCollector(string groupField, Sort sortWithinGroup)
-                : base(groupField, sortWithinGroup.GetSort().Length)
-            {
-                this.sortWithinGroup = sortWithinGroup;
-                groups = new HashMap<BytesRef, GroupHead>();
+        internal GeneralAllGroupHeadsCollector(string groupField, Sort sortWithinGroup)
+            : base(groupField, sortWithinGroup.GetSort().Length)
+        {
+            this.sortWithinGroup = sortWithinGroup;
+            groups = new HashMap<BytesRef, GroupHead>();
 
-                SortField[] sortFields = sortWithinGroup.GetSort();
-                for (int i = 0; i < sortFields.Length; i++)
-                {
-                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
-                }
+            SortField[] sortFields = sortWithinGroup.GetSort();
+            for (int i = 0; i < sortFields.Length; i++)
+            {
+                reversed[i] = sortFields[i].Reverse ? -1 : 1;
             }
+        }
 
-            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        {
+            int ord = groupIndex.GetOrd(doc);
+            BytesRef groupValue;
+            if (ord == -1)
             {
-                int ord = groupIndex.GetOrd(doc);
-                BytesRef groupValue;
-                if (ord == -1)
-                {
-                    groupValue = null;
-                }
-                else
-                {
-                    groupIndex.LookupOrd(ord, scratchBytesRef);
-                    groupValue = scratchBytesRef;
-                }
-                GroupHead groupHead;
-                if (!groups.TryGetValue(groupValue, out groupHead))
-                {
-                    groupHead = new GroupHead(this, groupValue, sortWithinGroup, doc);
-                    groups[groupValue == null ? null : BytesRef.DeepCopyOf(groupValue)] = groupHead;
-                    temporalResult.stop = true;
-                }
-                else
-                {
-                    temporalResult.stop = false;
-                }
-                temporalResult.groupHead = groupHead;
+                groupValue = null;
             }
-
-            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            else
             {
-                return groups.Values;
+                groupIndex.LookupOrd(ord, scratchBytesRef);
+                groupValue = scratchBytesRef;
             }
-
-            public override AtomicReaderContext NextReader
+            GroupHead groupHead;
+            if (!groups.TryGetValue(groupValue, out groupHead))
             {
-                set
-                {
-                    this.readerContext = value;
-                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
-
-                    foreach (GroupHead groupHead in groups.Values)
-                    {
-                        for (int i = 0; i < groupHead.comparators.Length; i++)
-                        {
-                            groupHead.comparators[i] = groupHead.comparators[i].SetNextReader(value);
-                        }
-                    }
-                }
+                groupHead = new GroupHead(this, groupValue, sortWithinGroup, doc);
+                groups[groupValue == null ? null : BytesRef.DeepCopyOf(groupValue)] = groupHead;
+                temporalResult.stop = true;
             }
-
-            public override Scorer Scorer
+            else
             {
-                set
-                {
-                    this.scorer = value;
-                    foreach (GroupHead groupHead in groups.Values)
-                    {
-                        foreach (FieldComparator comparator in groupHead.comparators)
-                        {
-                            comparator.Scorer = value;
-                        }
-                    }
-                }
+                temporalResult.stop = false;
             }
+            temporalResult.groupHead = groupHead;
+        }
 
-            internal class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
-            {
-                private readonly GeneralAllGroupHeadsCollector outerInstance;
-                public readonly BytesRef groupValue;
+        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        {
+            return groups.Values;
+        }
 
-                internal readonly FieldComparator[] comparators;
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+                this.readerContext = value;
+                groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
 
-                internal GroupHead(GeneralAllGroupHeadsCollector outerInstance, BytesRef groupValue, Sort sort, int doc)
-                    : base(doc + outerInstance.readerContext.DocBase)
+                foreach (GroupHead groupHead in groups.Values)
                 {
-                    this.outerInstance = outerInstance;
-                    SortField[] sortFields = sort.GetSort();
-                    comparators = new FieldComparator[sortFields.Length];
-                    for (int i = 0; i < sortFields.Length; i++)
+                    for (int i = 0; i < groupHead.comparators.Length; i++)
                     {
-                        comparators[i] = sortFields[i].GetComparator(1, i).SetNextReader(outerInstance.readerContext);
-                        comparators[i].Scorer = outerInstance.scorer;
-                        comparators[i].Copy(0, doc);
-                        comparators[i].Bottom = 0;
+                        groupHead.comparators[i] = groupHead.comparators[i].SetNextReader(value);
                     }
                 }
+            }
+        }
 
-                public override int Compare(int compIDX, int doc)
-                {
-                    return comparators[compIDX].CompareBottom(doc);
-                }
-
-                public override void UpdateDocHead(int doc)
+        public override Scorer Scorer
+        {
+            set
+            {
+                this.scorer = value;
+                foreach (GroupHead groupHead in groups.Values)
                 {
-                    foreach (FieldComparator comparator in comparators)
+                    foreach (FieldComparator comparator in groupHead.comparators)
                     {
-                        comparator.Copy(0, doc);
-                        comparator.Bottom = 0;
+                        comparator.Scorer = value;
                     }
-                    this.Doc = doc + outerInstance.readerContext.DocBase;
                 }
             }
         }
 
-
-        // AbstractAllGroupHeadsCollector optimized for ord fields and scores.
-        internal class OrdScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdScoreAllGroupHeadsCollector.GroupHead>
+        internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
         {
-            //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
-            private readonly SentinelIntSet ordSet;
-            private readonly IList<GroupHead> collectedGroups;
-            private readonly SortField[] fields;
+            private readonly GeneralAllGroupHeadsCollector outerInstance;
+            public readonly BytesRef groupValue;
 
-            private SortedDocValues[] sortsIndex;
-            private Scorer scorer;
-            private GroupHead[] segmentGroupHeads;
+            internal readonly FieldComparator[] comparators;
 
-            internal OrdScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
-                : base(groupField, sortWithinGroup.GetSort().Length)
+            internal GroupHead(GeneralAllGroupHeadsCollector outerInstance, BytesRef groupValue, Sort sort, int doc)
+                : base(doc + outerInstance.readerContext.DocBase)
             {
-                //this.outerInstance = outerInstance;
-                ordSet = new SentinelIntSet(initialSize, -2);
-                collectedGroups = new List<GroupHead>(initialSize);
+                this.outerInstance = outerInstance;
+                this.groupValue = groupValue;
 
-                SortField[] sortFields = sortWithinGroup.GetSort();
-                fields = new SortField[sortFields.Length];
-                sortsIndex = new SortedDocValues[sortFields.Length];
+                SortField[] sortFields = sort.GetSort();
+                comparators = new FieldComparator[sortFields.Length];
                 for (int i = 0; i < sortFields.Length; i++)
                 {
-                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
-                    fields[i] = sortFields[i];
+                    comparators[i] = sortFields[i].GetComparator(1, i).SetNextReader(outerInstance.readerContext);
+                    comparators[i].Scorer = outerInstance.scorer;
+                    comparators[i].Copy(0, doc);
+                    comparators[i].Bottom = 0;
                 }
             }
 
-            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            public override int Compare(int compIDX, int doc)
             {
-                return collectedGroups;
+                return comparators[compIDX].CompareBottom(doc);
             }
 
-            public override Scorer Scorer
+            public override void UpdateDocHead(int doc)
             {
-                set
+                foreach (FieldComparator comparator in comparators)
                 {
-                    this.scorer = value;
+                    comparator.Copy(0, doc);
+                    comparator.Bottom = 0;
                 }
+                this.Doc = doc + outerInstance.readerContext.DocBase;
             }
+        }
+    }
+
 
+    // AbstractAllGroupHeadsCollector optimized for ord fields and scores.
+    internal class OrdScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdScoreAllGroupHeadsCollector.GroupHead>
+    {
+        //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
+        private readonly SentinelIntSet ordSet;
+        private readonly IList<GroupHead> collectedGroups;
+        private readonly SortField[] fields;
 
-            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        private SortedDocValues[] sortsIndex;
+        private Scorer scorer;
+        private GroupHead[] segmentGroupHeads;
+
+        internal OrdScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+            : base(groupField, sortWithinGroup.GetSort().Length)
+        {
+            //this.outerInstance = outerInstance;
+            ordSet = new SentinelIntSet(initialSize, -2);
+            collectedGroups = new List<GroupHead>(initialSize);
+
+            SortField[] sortFields = sortWithinGroup.GetSort();
+            fields = new SortField[sortFields.Length];
+            sortsIndex = new SortedDocValues[sortFields.Length];
+            for (int i = 0; i < sortFields.Length; i++)
             {
-                int key = groupIndex.GetOrd(doc);
-                GroupHead groupHead;
-                if (!ordSet.Exists(key))
+                reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                fields[i] = sortFields[i];
+            }
+        }
+
+        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        {
+            return collectedGroups;
+        }
+
+        public override Scorer Scorer
+        {
+            set
+            {
+                this.scorer = value;
+            }
+        }
+
+
+        protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        {
+            int key = groupIndex.GetOrd(doc);
+            GroupHead groupHead;
+            if (!ordSet.Exists(key))
+            {
+                ordSet.Put(key);
+                BytesRef term;
+                if (key == -1)
                 {
-                    ordSet.Put(key);
-                    BytesRef term;
-                    if (key == -1)
-                    {
-                        term = null;
-                    }
-                    else
-                    {
-                        term = new BytesRef();
-                        groupIndex.LookupOrd(key, term);
-                    }
-                    groupHead = new GroupHead(this, doc, term);
-                    collectedGroups.Add(groupHead);
-                    segmentGroupHeads[key + 1] = groupHead;
-                    temporalResult.stop = true;
+                    term = null;
                 }
                 else
                 {
-                    temporalResult.stop = false;
-                    groupHead = segmentGroupHeads[key + 1];
+                    term = new BytesRef();
+                    groupIndex.LookupOrd(key, term);
                 }
-                temporalResult.groupHead = groupHead;
+                groupHead = new GroupHead(this, doc, term);
+                collectedGroups.Add(groupHead);
+                segmentGroupHeads[key + 1] = groupHead;
+                temporalResult.stop = true;
+            }
+            else
+            {
+                temporalResult.stop = false;
+                groupHead = segmentGroupHeads[key + 1];
             }
+            temporalResult.groupHead = groupHead;
+        }
 
-            public override AtomicReaderContext NextReader
+        public override AtomicReaderContext NextReader
+        {
+            set
             {
-                set
+                this.readerContext = value;
+                groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                for (int i = 0; i < fields.Length; i++)
                 {
-                    this.readerContext = value;
-                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
-                    for (int i = 0; i < fields.Length; i++)
+                    if (fields[i].Type == SortField.Type_e.SCORE)
                     {
-                        if (fields[i].Type == SortField.Type_e.SCORE)
-                        {
-                            continue;
-                        }
-
-                        sortsIndex[i] = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, fields[i].Field);
+                        continue;
                     }
 
-                    // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
-                    ordSet.Clear();
-                    segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
-                    foreach (GroupHead collectedGroup in collectedGroups)
+                    sortsIndex[i] = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, fields[i].Field);
+                }
+
+                // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                ordSet.Clear();
+                segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
+                foreach (GroupHead collectedGroup in collectedGroups)
+                {
+                    int ord;
+                    if (collectedGroup.groupValue == null)
                     {
-                        int ord;
-                        if (collectedGroup.groupValue == null)
-                        {
-                            ord = -1;
-                        }
-                        else
-                        {
-                            ord = groupIndex.LookupTerm(collectedGroup.groupValue);
-                        }
-                        if (collectedGroup.groupValue == null || ord >= 0)
-                        {
-                            ordSet.Put(ord);
-                            segmentGroupHeads[ord + 1] = collectedGroup;
+                        ord = -1;
+                    }
+                    else
+                    {
+                        ord = groupIndex.LookupTerm(collectedGroup.groupValue);
+                    }
+                    if (collectedGroup.groupValue == null || ord >= 0)
+                    {
+                        ordSet.Put(ord);
+                        segmentGroupHeads[ord + 1] = collectedGroup;
 
-                            for (int i = 0; i < sortsIndex.Length; i++)
+                        for (int i = 0; i < sortsIndex.Length; i++)
+                        {
+                            if (fields[i].Type == SortField.Type_e.SCORE)
+                            {
+                                continue;
+                            }
+                            int sortOrd;
+                            if (collectedGroup.sortValues[i] == null)
                             {
-                                if (fields[i].Type == SortField.Type_e.SCORE)
-                                {
-                                    continue;
-                                }
-                                int sortOrd;
-                                if (collectedGroup.sortValues[i] == null)
-                                {
-                                    sortOrd = -1;
-                                }
-                                else
-                                {
-                                    sortOrd = sortsIndex[i].LookupTerm(collectedGroup.sortValues[i]);
-                                }
-                                collectedGroup.sortOrds[i] = sortOrd;
+                                sortOrd = -1;
                             }
+                            else
+                            {
+                                sortOrd = sortsIndex[i].LookupTerm(collectedGroup.sortValues[i]);
+                            }
+                            collectedGroup.sortOrds[i] = sortOrd;
                         }
                     }
                 }
-
             }
 
-            internal class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
-            {
-                private readonly OrdScoreAllGroupHeadsCollector outerInstance;
-                public readonly BytesRef groupValue;
+        }
+
+        internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+        {
+            private readonly OrdScoreAllGroupHeadsCollector outerInstance;
+            public readonly BytesRef groupValue;
 
-                internal BytesRef[] sortValues;
-                internal int[] sortOrds;
-                internal float[] scores;
+            internal BytesRef[] sortValues;
+            internal int[] sortOrds;
+            internal float[] scores;
 
-                internal GroupHead(OrdScoreAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
-                    : base(doc + outerInstance.readerContext.DocBase)
-                {
-                    this.outerInstance = outerInstance;
-                    this.groupValue = groupValue;
+            internal GroupHead(OrdScoreAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
+                : base(doc + outerInstance.readerContext.DocBase)
+            {
+                this.outerInstance = outerInstance;
+                this.groupValue = groupValue;
 
-                    sortValues = new BytesRef[outerInstance.sortsIndex.Length];
-                    sortOrds = new int[outerInstance.sortsIndex.Length];
-                    scores = new float[outerInstance.sortsIndex.Length];
-                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                sortValues = new BytesRef[outerInstance.sortsIndex.Length];
+                sortOrds = new int[outerInstance.sortsIndex.Length];
+                scores = new float[outerInstance.sortsIndex.Length];
+                for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                {
+                    if (outerInstance.fields[i].Type == SortField.Type_e.SCORE)
                     {
-                        if (outerInstance.fields[i].Type == SortField.Type_e.SCORE)
-                        {
-                            scores[i] = outerInstance.scorer.Score();
-                        }
-                        else
+                        scores[i] = outerInstance.scorer.Score();
+                    }
+                    else
+                    {
+                        sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                        sortValues[i] = new BytesRef();
+                        if (sortOrds[i] != -1)
                         {
-                            sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
-                            sortValues[i] = new BytesRef();
-                            if (sortOrds[i] != -1)
-                            {
-                                outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
-                            }
+                            outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
                         }
                     }
                 }
+            }
 
-                public override int Compare(int compIDX, int doc)
+            public override int Compare(int compIDX, int doc)
+            {
+                if (outerInstance.fields[compIDX].Type == SortField.Type_e.SCORE)
                 {
-                    if (outerInstance.fields[compIDX].Type == SortField.Type_e.SCORE)
+                    float score = outerInstance.scorer.Score();
+                    if (scores[compIDX] < score)
                     {
-                        float score = outerInstance.scorer.Score();
-                        if (scores[compIDX] < score)
-                        {
-                            return 1;
-                        }
-                        else if (scores[compIDX] > score)
-                        {
-                            return -1;
-                        }
-                        return 0;
+                        return 1;
                     }
-                    else
+                    else if (scores[compIDX] > score)
+                    {
+                        return -1;
+                    }
+                    return 0;
+                }
+                else
+                {
+                    if (sortOrds[compIDX] < 0)
                     {
-                        if (sortOrds[compIDX] < 0)
+                        // The current segment doesn't contain the sort value we encountered before. Therefore the ord is negative.
+                        if (outerInstance.sortsIndex[compIDX].GetOrd(doc) == -1)
                         {
-                            // The current segment doesn't contain the sort value we encountered before. Therefore the ord is negative.
-                            if (outerInstance.sortsIndex[compIDX].GetOrd(doc) == -1)
-                            {
-                                outerInstance.scratchBytesRef.Length = 0;
-                            }
-                            else
-                            {
-                                outerInstance.sortsIndex[compIDX].Get(doc, outerInstance.scratchBytesRef);
-                            }
-                            return sortValues[compIDX].CompareTo(outerInstance.scratchBytesRef);
+                            outerInstance.scratchBytesRef.Length = 0;
                         }
                         else
                         {
-                            return sortOrds[compIDX] - outerInstance.sortsIndex[compIDX].GetOrd(doc);
+                            outerInstance.sortsIndex[compIDX].Get(doc, outerInstance.scratchBytesRef);
                         }
+                        return sortValues[compIDX].CompareTo(outerInstance.scratchBytesRef);
+                    }
+                    else
+                    {
+                        return sortOrds[compIDX] - outerInstance.sortsIndex[compIDX].GetOrd(doc);
                     }
                 }
+            }
 
-                public override void UpdateDocHead(int doc)
+            public override void UpdateDocHead(int doc)
+            {
+                for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
                 {
-                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    if (outerInstance.fields[i].Type == Search.SortField.Type_e.SCORE)
                     {
-                        if (outerInstance.fields[i].Type == Search.SortField.Type_e.SCORE)
+                        scores[i] = outerInstance.scorer.Score();
+                    }
+                    else
+                    {
+                        sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                        if (sortOrds[i] == -1)
                         {
-                            scores[i] = outerInstance.scorer.Score();
+                            sortValues[i].Length = 0;
                         }
                         else
                         {
-                            sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
-                            if (sortOrds[i] == -1)
-                            {
-                                sortValues[i].Length = 0;
-                            }
-                            else
-                            {
-                                outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
-                            }
+                            outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
                         }
                     }
-                    this.Doc = doc + outerInstance.readerContext.DocBase;
                 }
+                this.Doc = doc + outerInstance.readerContext.DocBase;
             }
         }
+    }
 
 
-        // AbstractAllGroupHeadsCollector optimized for ord fields.
-        internal class OrdAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdAllGroupHeadsCollector.GroupHead>
-        {
-            //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
-            private readonly SentinelIntSet ordSet;
-            private readonly IList<GroupHead> collectedGroups;
-            private readonly SortField[] fields;
+    // AbstractAllGroupHeadsCollector optimized for ord fields.
+    internal class OrdAllGroupHeadsCollector : TermAllGroupHeadsCollector<OrdAllGroupHeadsCollector.GroupHead>
+    {
+        //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
+        private readonly SentinelIntSet ordSet;
+        private readonly IList<GroupHead> collectedGroups;
+        private readonly SortField[] fields;
 
-            private SortedDocValues[] sortsIndex;
-            private GroupHead[] segmentGroupHeads;
+        private SortedDocValues[] sortsIndex;
+        private GroupHead[] segmentGroupHeads;
 
-            internal OrdAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
-                        : base(groupField, sortWithinGroup.GetSort().Length)
+        internal OrdAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+                    : base(groupField, sortWithinGroup.GetSort().Length)
+        {
+            //this.outerInstance = outerInstance;
+            ordSet = new SentinelIntSet(initialSize, -2);
+            collectedGroups = new List<GroupHead>(initialSize);
+
+            SortField[] sortFields = sortWithinGroup.GetSort();
+            fields = new SortField[sortFields.Length];
+            sortsIndex = new SortedDocValues[sortFields.Length];
+            for (int i = 0; i < sortFields.Length; i++)
             {
-                //this.outerInstance = outerInstance;
-                ordSet = new SentinelIntSet(initialSize, -2);
-                collectedGroups = new List<GroupHead>(initialSize);
-
-                SortField[] sortFields = sortWithinGroup.GetSort();
-                fields = new SortField[sortFields.Length];
-                sortsIndex = new SortedDocValues[sortFields.Length];
-                for (int i = 0; i < sortFields.Length; i++)
-                {
-                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
-                    fields[i] = sortFields[i];
-                }
+                reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                fields[i] = sortFields[i];
             }
+        }
 
-            protected override ICollection<GroupHead> GetCollectedGroupHeads()
-            {
-                return collectedGroups;
-            }
+        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        {
+            return collectedGroups;
+        }
 
-            public override Scorer Scorer
+        public override Scorer Scorer
+        {
+            set
             {
-                set
-                {
-                }
             }
+        }
 
 
-            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        {
+            int key = groupIndex.GetOrd(doc);
+            GroupHead groupHead;
+            if (!ordSet.Exists(key))
             {
-                int key = groupIndex.GetOrd(doc);
-                GroupHead groupHead;
-                if (!ordSet.Exists(key))
+                ordSet.Put(key);
+                BytesRef term;
+                if (key == -1)
                 {
-                    ordSet.Put(key);
-                    BytesRef term;
-                    if (key == -1)
-                    {
-                        term = null;
-                    }
-                    else
-                    {
-                        term = new BytesRef();
-                        groupIndex.LookupOrd(key, term);
-                    }
-                    groupHead = new GroupHead(this, doc, term);
-                    collectedGroups.Add(groupHead);
-                    segmentGroupHeads[key + 1] = groupHead;
-                    temporalResult.stop = true;
+                    term = null;
                 }
                 else
                 {
-                    temporalResult.stop = false;
-                    groupHead = segmentGroupHeads[key + 1];
+                    term = new BytesRef();
+                    groupIndex.LookupOrd(key, term);
                 }
-                temporalResult.groupHead = groupHead;
+                groupHead = new GroupHead(this, doc, term);
+                collectedGroups.Add(groupHead);
+                segmentGroupHeads[key + 1] = groupHead;
+                temporalResult.stop = true;
             }
+            else
+            {
+                temporalResult.stop = false;
+                groupHead = segmentGroupHeads[key + 1];
+            }
+            temporalResult.groupHead = groupHead;
+        }
 
-            public override AtomicReaderContext NextReader
+        public override AtomicReaderContext NextReader
+        {
+            set
             {
-                set
+                this.readerContext = value;
+                groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
+                for (int i = 0; i < fields.Length; i++)
+                {
+                    sortsIndex[i] = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, fields[i].Field);
+                }
+
+                // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                ordSet.Clear();
+                segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
+                foreach (GroupHead collectedGroup in collectedGroups)
                 {
-                    this.readerContext = value;
-                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
-                    for (int i = 0; i < fields.Length; i++)
+                    int groupOrd;
+                    if (collectedGroup.groupValue == null)
                     {
-                        sortsIndex[i] = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, fields[i].Field);
+                        groupOrd = -1;
                     }
-
-                    // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
-                    ordSet.Clear();
-                    segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
-                    foreach (GroupHead collectedGroup in collectedGroups)
+                    else
                     {
-                        int groupOrd;
-                        if (collectedGroup.groupValue == null)
-                        {
-                            groupOrd = -1;
-                        }
-                        else
-                        {
-                            groupOrd = groupIndex.LookupTerm(collectedGroup.groupValue);
-                        }
-                        if (collectedGroup.groupValue == null || groupOrd >= 0)
-                        {
-                            ordSet.Put(groupOrd);
-                            segmentGroupHeads[groupOrd + 1] = collectedGroup;
+                        groupOrd = groupIndex.LookupTerm(collectedGroup.groupValue);
+                    }
+                    if (collectedGroup.groupValue == null || groupOrd >= 0)
+                    {
+                        ordSet.Put(groupOrd);
+                        segmentGroupHeads[groupOrd + 1] = collectedGroup;
 
-                            for (int i = 0; i < sortsIndex.Length; i++)
+                        for (int i = 0; i < sortsIndex.Length; i++)
+                        {
+                            int sortOrd;
+                            if (collectedGroup.sortOrds[i] == -1)
                             {
-                                int sortOrd;
-                                if (collectedGroup.sortOrds[i] == -1)
-                                {
-                                    sortOrd = -1;
-                                }
-                                else
-                                {
-                                    sortOrd = sortsIndex[i].LookupTerm(collectedGroup.sortValues[i]);
-                                }
-                                collectedGroup.sortOrds[i] = sortOrd;
+                                sortOrd = -1;
                             }
+                            else
+                            {
+                                sortOrd = sortsIndex[i].LookupTerm(collectedGroup.sortValues[i]);
+                            }
+                            collectedGroup.sortOrds[i] = sortOrd;
                         }
                     }
                 }
             }
+        }
 
-            internal class GroupHead : AbstractGroupHead /* AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+        internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /* AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+        {
+            private readonly OrdAllGroupHeadsCollector outerInstance;
+            public readonly BytesRef groupValue;
+            internal BytesRef[] sortValues;
+            internal int[] sortOrds;
+
+            internal GroupHead(OrdAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
+                : base(doc + outerInstance.readerContext.DocBase)
             {
-                private readonly OrdAllGroupHeadsCollector outerInstance;
-                public readonly BytesRef groupValue;
-                internal BytesRef[] sortValues;
-                internal int[] sortOrds;
+                this.outerInstance = outerInstance;
+                this.groupValue = groupValue;
 
-                internal GroupHead(OrdAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
-                    : base(doc + outerInstance.readerContext.DocBase)
+                sortValues = new BytesRef[outerInstance.sortsIndex.Length];
+                sortOrds = new int[outerInstance.sortsIndex.Length];
+                for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
                 {
-                    this.outerInstance = outerInstance;
-                    this.groupValue = groupValue;
-
-                    sortValues = new BytesRef[outerInstance.sortsIndex.Length];
-                    sortOrds = new int[outerInstance.sortsIndex.Length];
-                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                    sortValues[i] = new BytesRef();
+                    if (sortOrds[i] != -1)
                     {
-                        sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
-                        sortValues[i] = new BytesRef();
-                        if (sortOrds[i] != -1)
-                        {
-                            outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
-                        }
+                        outerInstance.sortsIndex[i].Get(doc, sortValues[i]);
                     }
                 }
+            }
 
-                public override int Compare(int compIDX, int doc)
+            public override int Compare(int compIDX, int doc)
+            {
+                if (sortOrds[compIDX] < 0)
                 {
-                    if (sortOrds[compIDX] < 0)
+                    // The current segment doesn't contain the sort value we encountered before. Therefore the ord is negative.
+                    if (outerInstance.sortsIndex[compIDX].GetOrd(doc) == -1)
                     {
-                        // The current segment doesn't contain the sort value we encountered before. Therefore the ord is negative.
-                        if (outerInstance.sortsIndex[compIDX].GetOrd(doc) == -1)
-                        {
-                            outerInstance.scratchBytesRef.Length = 0;
-                        }
-                        else
-                        {
-                            outerInstance.sortsIndex[compIDX].Get(doc, outerInstance.scratchBytesRef);
-                        }
-                        return sortValues[compIDX].CompareTo(outerInstance.scratchBytesRef);
+                        outerInstance.scratchBytesRef.Length = 0;
                     }
                     else
                     {
-                        return sortOrds[compIDX] - outerInstance.sortsIndex[compIDX].GetOrd(doc);
+                        outerInstance.sortsIndex[compIDX].Get(doc, outerInstance.scratchBytesRef);
                     }
+                    return sortValues[compIDX].CompareTo(outerInstance.scratchBytesRef);
+                }
+                else
+                {
+                    return sortOrds[compIDX] - outerInstance.sortsIndex[compIDX].GetOrd(doc);
                 }
+            }
 
-                public override void UpdateDocHead(int doc)
+            public override void UpdateDocHead(int doc)
+            {
+                for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
                 {
-                    for (int i = 0; i < outerInstance.sortsIndex.Length; i++)
+                    sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
+                    if (sortOrds[i] == -1)
                     {
-                        sortOrds[i] = outerInstance.sortsIndex[i].GetOrd(doc);
-                        if (sortOrds[i] == -1)
-                        {
-                            sortValues[i].Length = 0;
-                        }
-                        else
-                        {
-                            outerInstance.sortsIndex[i].LookupOrd(sortOrds[i], sortValues[i]);
-                        }
+                        sortValues[i].Length = 0;
+                    }
+                    else
+                    {
+                        outerInstance.sortsIndex[i].LookupOrd(sortOrds[i], sortValues[i]);
                     }
-                    this.Doc = doc + outerInstance.readerContext.DocBase;
                 }
-
+                this.Doc = doc + outerInstance.readerContext.DocBase;
             }
 
         }
 
+    }
 
-        // AbstractAllGroupHeadsCollector optimized for scores.
-        internal class ScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<ScoreAllGroupHeadsCollector.GroupHead>
-        {
-            //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
-            private readonly SentinelIntSet ordSet;
-            private readonly IList<GroupHead> collectedGroups;
-            private readonly SortField[] fields;
 
-            private Scorer scorer;
-            private GroupHead[] segmentGroupHeads;
+    // AbstractAllGroupHeadsCollector optimized for scores.
+    internal class ScoreAllGroupHeadsCollector : TermAllGroupHeadsCollector<ScoreAllGroupHeadsCollector.GroupHead>
+    {
+        //private readonly TermAllGroupHeadsCollector<GH> outerInstance;
+        private readonly SentinelIntSet ordSet;
+        private readonly IList<GroupHead> collectedGroups;
+        private readonly SortField[] fields;
 
-            internal ScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
-                        : base(groupField, sortWithinGroup.GetSort().Length)
-            {
-                //this.outerInstance = outerInstance;
-                ordSet = new SentinelIntSet(initialSize, -2);
-                collectedGroups = new List<GroupHead>(initialSize);
+        private Scorer scorer;
+        private GroupHead[] segmentGroupHeads;
 
-                SortField[] sortFields = sortWithinGroup.GetSort();
-                fields = new SortField[sortFields.Length];
-                for (int i = 0; i < sortFields.Length; i++)
-                {
-                    reversed[i] = sortFields[i].Reverse ? -1 : 1;
-                    fields[i] = sortFields[i];
-                }
-            }
+        internal ScoreAllGroupHeadsCollector(/*TermAllGroupHeadsCollector<GH> outerInstance,*/ string groupField, Sort sortWithinGroup, int initialSize)
+                    : base(groupField, sortWithinGroup.GetSort().Length)
+        {
+            //this.outerInstance = outerInstance;
+            ordSet = new SentinelIntSet(initialSize, -2);
+            collectedGroups = new List<GroupHead>(initialSize);
 
-            protected override ICollection<GroupHead> GetCollectedGroupHeads()
+            SortField[] sortFields = sortWithinGroup.GetSort();
+            fields = new SortField[sortFields.Length];
+            for (int i = 0; i < sortFields.Length; i++)
             {
-                return collectedGroups;
+                reversed[i] = sortFields[i].Reverse ? -1 : 1;
+                fields[i] = sortFields[i];
             }
+        }
 
-            public override Scorer Scorer
+        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        {
+            return collectedGroups;
+        }
+
+        public override Scorer Scorer
+        {
+            set
             {
-                set
-                {
-                    this.scorer = value;
-                }
+                this.scorer = value;
             }
+        }
 
-            protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        protected override void RetrieveGroupHeadAndAddIfNotExist(int doc)
+        {
+            int key = groupIndex.GetOrd(doc);
+            GroupHead groupHead;
+            if (!ordSet.Exists(key))
             {
-                int key = groupIndex.GetOrd(doc);
-                GroupHead groupHead;
-                if (!ordSet.Exists(key))
+                ordSet.Put(key);
+                BytesRef term;
+                if (key == -1)
                 {
-                    ordSet.Put(key);
-                    BytesRef term;
-                    if (key == -1)
-                    {
-                        term = null;
-                    }
-                    else
-                    {
-                        term = new BytesRef();
-                        groupIndex.LookupOrd(key, term);
-                    }
-                    groupHead = new GroupHead(this, doc, term);
-                    collectedGroups.Add(groupHead);
-                    segmentGroupHeads[key + 1] = groupHead;
-                    temporalResult.stop = true;
+                    term = null;
                 }
                 else
                 {
-                    temporalResult.stop = false;
-                    groupHead = segmentGroupHeads[key + 1];
+                    term = new BytesRef();
+                    groupIndex.LookupOrd(key, term);
                 }
-                temporalResult.groupHead = groupHead;
+                groupHead = new GroupHead(this, doc, term);
+                collectedGroups.Add(groupHead);
+                segmentGroupHeads[key + 1] = groupHead;
+                temporalResult.stop = true;
             }
-            public override AtomicReaderContext NextReader
+            else
             {
-                set
-                {
-                    this.readerContext = value;
-                    groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
-
-                    // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
-                    ordSet.Clear();
-                    segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
-                    foreach (GroupHead collectedGroup in collectedGroups)
-                    {
-                        int ord;
-                        if (collectedGroup.groupValue == null)
-                        {
-                            ord = -1;
-                        }
-                        else
-                        {
-                            ord = groupIndex.LookupTerm(collectedGroup.groupValue);
-                        }
-                        if (collectedGroup.groupValue == null || ord >= 0)
-                        {
-                            ordSet.Put(ord);
-                            segmentGroupHeads[ord + 1] = collectedGroup;
-                        }
-                    }
-                }
+                temporalResult.stop = false;
+                groupHead = segmentGroupHeads[key + 1];
             }
-
-            internal class GroupHead : AbstractGroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+            temporalResult.groupHead = groupHead;
+        }
+        public override AtomicReaderContext NextReader
+        {
+            set
             {
-                private readonly ScoreAllGroupHeadsCollector outerInstance;
-                public readonly BytesRef groupValue;
-                internal float[] scores;
+                this.readerContext = value;
+                groupIndex = FieldCache.DEFAULT.GetTermsIndex(value.AtomicReader, groupField);
 
-                internal GroupHead(ScoreAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
-                    : base(doc + outerInstance.readerContext.DocBase)
+                // Clear ordSet and fill it with previous encountered groups that can occur in the current segment.
+                ordSet.Clear();
+                segmentGroupHeads = new GroupHead[groupIndex.ValueCount + 1];
+                foreach (GroupHead collectedGroup in collectedGroups)
                 {
-                    this.outerInstance = outerInstance;
-                    this.groupValue = groupValue;
-
-                    scores = new float[outerInstance.fields.Length];
-                    float score = outerInstance.scorer.Score();
-                    for (int i = 0; i < scores.Length; i++)
+                    int ord;
+                    if (collectedGroup.groupValue == null)
                     {
-                        scores[i] = score;
+                        ord = -1;
                     }
-                }
-
-                public override int Compare(int compIDX, int doc)
-                {
-                    float score = outerInstance.scorer.Score();
-                    if (scores[compIDX] < score)
+                    else
                     {
-                        return 1;
+                        ord = groupIndex.LookupTerm(collectedGroup.groupValue);
                     }
-                    else if (scores[compIDX] > score)
+                    if (collectedGroup.groupValue == null || ord >= 0)
                     {
-                        return -1;
+                        ordSet.Put(ord);
+                        segmentGroupHeads[ord + 1] = collectedGroup;
                     }
-                    return 0;
                 }
+            }
+        }
+
+        internal class GroupHead : AbstractAllGroupHeadsCollector_GroupHead /*AbstractAllGroupHeadsCollector.GroupHead<BytesRef>*/
+        {
+            private readonly ScoreAllGroupHeadsCollector outerInstance;
+            public readonly BytesRef groupValue;
+            internal float[] scores;
+
+            internal GroupHead(ScoreAllGroupHeadsCollector outerInstance, int doc, BytesRef groupValue)
+                : base(doc + outerInstance.readerContext.DocBase)
+            {
+                this.outerInstance = outerInstance;
+                this.groupValue = groupValue;
 
-                public override void UpdateDocHead(int doc)
+                scores = new float[outerInstance.fields.Length];
+                float score = outerInstance.scorer.Score();
+                for (int i = 0; i < scores.Length; i++)
                 {
-                    float score = outerInstance.scorer.Score();
-                    for (int i = 0; i < scores.Length; i++)
-                    {
-                        scores[i] = score;
-                    }
-                    this.Doc = doc + outerInstance.readerContext.DocBase;
+                    scores[i] = score;
                 }
-
             }
 
-        
+            public override int Compare(int compIDX, int doc)
+            {
+                float score = outerInstance.scorer.Score();
+                if (scores[compIDX] < score)
+                {
+                    return 1;
+                }
+                else if (scores[compIDX] > score)
+                {
+                    return -1;
+                }
+                return 0;
+            }
 
+            public override void UpdateDocHead(int doc)
+            {
+                float score = outerInstance.scorer.Score();
+                for (int i = 0; i < scores.Length; i++)
+                {
+                    scores[i] = score;
+                }
+                this.Doc = doc + outerInstance.readerContext.DocBase;
+            }
 
+        }
     }
 }


[37/58] [abbrv] lucenenet git commit: Completed implementation of the Grouping.AbstractGroupFacetCollector using the TreeSet.

Posted by ni...@apache.org.
Completed implementation of the Grouping.AbstractGroupFacetCollector using the TreeSet.


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

Branch: refs/heads/grouping
Commit: a8f7f42aedd968ae73a4bc1be3b55294ec66521f
Parents: b689479
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Oct 27 18:46:13 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:54 2016 +0700

----------------------------------------------------------------------
 .../AbstractGroupFacetCollector.cs              | 22 ++++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a8f7f42a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
index 1cc4574..9769871 100644
--- a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
@@ -1,4 +1,5 @@
 \ufeffusing Lucene.Net.Search;
+using Lucene.Net.Support;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
@@ -164,7 +165,7 @@ namespace Lucene.Net.Search.Grouping
             //    };
 
             private readonly int maxSize;
-            private readonly SortedSet<FacetEntry> facetEntries;
+            private readonly TreeSet<FacetEntry> facetEntries;
             private readonly int totalMissingCount;
             private readonly int totalCount;
 
@@ -172,7 +173,7 @@ namespace Lucene.Net.Search.Grouping
 
             public GroupedFacetResult(int size, int minCount, bool orderByCount, int totalCount, int totalMissingCount)
             {
-                this.facetEntries = new SortedSet<FacetEntry>(orderByCount ? orderByCountAndValue : orderByValue);
+                this.facetEntries = new TreeSet<FacetEntry>(orderByCount ? orderByCountAndValue : orderByValue);
                 this.totalMissingCount = totalMissingCount;
                 this.totalCount = totalCount;
                 maxSize = size;
@@ -189,19 +190,18 @@ namespace Lucene.Net.Search.Grouping
                 FacetEntry facetEntry = new FacetEntry(facetValue, count);
                 if (facetEntries.Count == maxSize)
                 {
-                    // LUCENENET TODO: Add the C5.TreeSet to Support?
-                    // LUCENENET TODO: Finish implementation
-                    //if (facetEntries.Higher(facetEntry) == null)
-                    //{
-                    //    return;
-                    //}
-                    facetEntries.Remove(facetEntries.Last());
+                    FacetEntry temp;
+                    if (!facetEntries.TrySuccessor(facetEntry, out temp))
+                    {
+                        return;
+                    }
+                    facetEntries.DeleteMax();
                 }
                 facetEntries.Add(facetEntry);
 
                 if (facetEntries.Count == maxSize)
                 {
-                    currentMin = facetEntries.Last().Count;
+                    currentMin = facetEntries.FindMax().Count;
                 }
             }
 
@@ -359,7 +359,7 @@ namespace Lucene.Net.Search.Grouping
 
         }
 
-        private class SegmentResultPriorityQueue : PriorityQueue<AbstractSegmentResult>
+        private class SegmentResultPriorityQueue : Util.PriorityQueue<AbstractSegmentResult>
         {
             internal SegmentResultPriorityQueue(int maxSize)
                 : base(maxSize)


[20/58] [abbrv] lucenenet git commit: Revert "HACK: Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context."

Posted by ni...@apache.org.
Revert "HACK: Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context."

This reverts commit 4dbc3590361814d13fae64c8d030820eb4987489.


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

Branch: refs/heads/grouping
Commit: d67ed2b2a602a6528fa990bd5636f7cba01546b1
Parents: 7723e26
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Tue Nov 8 02:18:54 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:23:39 2016 +0700

----------------------------------------------------------------------
 .../BaseCompressingDocValuesFormatTestCase.cs   |   3 -
 .../Index/BaseDocValuesFormatTestCase.cs        | 156 +++---
 .../Index/BaseIndexFileFormatTestCase.cs        |   2 +-
 .../Index/BasePostingsFormatTestCase.cs         |  14 +-
 .../Index/BaseStoredFieldsFormatTestCase.cs     |  22 +-
 .../Index/BaseTermVectorsFormatTestCase.cs      |  14 +-
 .../Util/BaseDocIdSetTestCase.cs                |  10 +-
 .../BlockTerms/TestFixedGapPostingsFormat.cs    |  63 ---
 .../Bloom/TestBloomPostingsFormat.cs            |  63 ---
 .../DiskDv/TestDiskDocValuesFormat.cs           | 526 ------------------
 .../IntBlock/TestFixedIntBlockPostingsFormat.cs |  63 ---
 .../TestVariableIntBlockPostingsFormat.cs       |  63 ---
 .../Memory/TestDirectDocValuesFormat.cs         | 501 ------------------
 .../Memory/TestDirectPostingsFormat.cs          |  63 ---
 .../Memory/TestFSTOrdPostingsFormat.cs          |  63 ---
 .../Memory/TestFSTOrdPulsing41PostingsFormat.cs |  63 ---
 .../Memory/TestFSTPostingsFormat.cs             |  63 ---
 .../Memory/TestFSTPulsing41PostingsFormat.cs    |  63 ---
 .../Memory/TestMemoryDocValuesFormat.cs         | 526 ------------------
 .../Memory/TestMemoryPostingsFormat.cs          |  62 ---
 .../Pulsing/TestPulsingPostingsFormat.cs        |  63 ---
 .../Sep/TestSepPostingsFormat.cs                |  62 ---
 .../SimpleText/TestSimpleTextDocValuesFormat.cs | 500 ------------------
 .../SimpleText/TestSimpleTextPostingsFormat.cs  |  63 ---
 .../TestSimpleTextStoredFieldsFormat.cs         |  88 ----
 .../TestSimpleTextTermVectorsFormat.cs          |  66 ---
 .../Index/Sorter/IndexSortingTest.cs            |  56 --
 .../Index/Sorter/SorterTestBase.cs              |  16 +-
 .../Index/Sorter/SortingAtomicReaderTest.cs     |  56 --
 .../Classic/TestQueryParser.cs                  | 250 ---------
 .../Ext/TestExtendableQueryParser.cs            | 369 -------------
 .../Compressing/AbstractTestCompressionMode.cs  |  14 +-
 .../AbstractTestLZ4CompressionMode.cs           |   8 +-
 .../TestCompressingStoredFieldsFormat.cs        |  89 ----
 .../TestCompressingTermVectorsFormat.cs         |  67 ---
 .../Compressing/TestFastCompressionMode.cs      |  81 ---
 .../Compressing/TestFastDecompressionMode.cs    |  81 ---
 .../Compressing/TestHighCompressionMode.cs      |  50 --
 .../Lucene3x/TestLucene3xPostingsFormat.cs      |  63 ---
 .../Lucene3x/TestLucene3xStoredFieldsFormat.cs  |  84 ---
 .../Lucene3x/TestLucene3xTermVectorsFormat.cs   |  67 ---
 .../Lucene40/TestLucene40DocValuesFormat.cs     | 501 ------------------
 .../Lucene40/TestLucene40PostingsFormat.cs      |  63 ---
 .../Lucene40/TestLucene40StoredFieldsFormat.cs  |  89 ----
 .../Lucene40/TestLucene40TermVectorsFormat.cs   |  67 ---
 .../Codecs/Lucene41/TestBlockPostingsFormat.cs  |  65 ---
 .../Lucene41/TestLucene41StoredFieldsFormat.cs  |  89 ----
 .../Lucene42/TestLucene42DocValuesFormat.cs     | 526 ------------------
 .../Lucene45/TestLucene45DocValuesFormat.cs     | 527 -------------------
 .../Perfield/TestPerFieldDocValuesFormat.cs     | 501 ------------------
 .../Perfield/TestPerFieldPostingsFormat.cs      |  51 --
 .../core/Index/TestDocValuesFormat.cs           | 503 ------------------
 .../core/Index/TestLogMergePolicy.cs            |  15 -
 .../core/Index/TestNumericDocValuesUpdates.cs   |   2 +-
 .../TestPersistentSnapshotDeletionPolicy.cs     |  50 --
 .../core/Index/TestPostingsFormat.cs            |  50 --
 .../core/Index/TestStoredFieldsFormat.cs        |  83 ---
 .../core/Index/TestTermVectorsFormat.cs         |  55 --
 .../core/Index/TestTieredMergePolicy.cs         |  14 -
 .../core/Search/BaseTestRangeFilter.cs          |   2 +-
 .../Spans/TestSpanExplanationsOfNonMatches.cs   | 214 --------
 .../TestComplexExplanationsOfNonMatches.cs      | 160 ------
 .../core/Search/TestExplanations.cs             |   2 +-
 .../core/Search/TestFieldCacheRangeFilter.cs    |  14 -
 .../core/Search/TestFieldCacheRewriteMethod.cs  |  17 -
 .../core/Search/TestMultiTermConstantScore.cs   |  14 -
 .../core/Search/TestSimpleExplanations.cs       |  19 -
 .../TestSimpleExplanationsOfNonMatches.cs       | 452 ----------------
 .../core/Search/TestTermRangeFilter.cs          |  14 -
 .../core/Support/TestLurchTable.cs              | 176 +------
 .../core/Util/BaseSortTestCase.cs               |  18 +-
 .../core/Util/Packed/TestEliasFanoDocIdSet.cs   |  45 --
 .../core/Util/TestDocIdBitSet.cs                |  46 --
 .../core/Util/TestFixedBitSet.cs                |  45 --
 .../core/Util/TestInPlaceMergeSorter.cs         |  64 ---
 .../core/Util/TestIntroSorter.cs                |  64 ---
 .../core/Util/TestOpenBitSet.cs                 |  44 --
 .../core/Util/TestPForDeltaDocIdSet.cs          |  44 --
 src/Lucene.Net.Tests/core/Util/TestTimSorter.cs |  64 ---
 .../core/Util/TestWAH8DocIdSet.cs               |  44 --
 80 files changed, 159 insertions(+), 9250 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
index 54d7fd5..d88ecb4 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseCompressingDocValuesFormatTestCase.cs
@@ -45,7 +45,6 @@ namespace Lucene.Net.Index
             return size;
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestUniqueValuesCompression()
         {
             Directory dir = new RAMDirectory();
@@ -86,7 +85,6 @@ namespace Lucene.Net.Index
             Assert.IsTrue(size2 < size1 + 8 * 20);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDateCompression()
         {
             Directory dir = new RAMDirectory();
@@ -117,7 +115,6 @@ namespace Lucene.Net.Index
             Assert.IsTrue(size2 < size1 + (PackedInts.BitsRequired(day) * 50) / 8);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSingleBigValueCompression()
         {
             Directory dir = new RAMDirectory();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
index fa46ef8..ebc4c19 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseDocValuesFormatTestCase.cs
@@ -84,7 +84,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestOneNumber()
         {
             Directory directory = NewDirectory();
@@ -119,7 +119,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestOneFloat()
         {
             Directory directory = NewDirectory();
@@ -154,7 +154,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoNumbers()
         {
             Directory directory = NewDirectory();
@@ -192,7 +192,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoBinaryValues()
         {
             Directory directory = NewDirectory();
@@ -233,7 +233,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoFieldsMixed()
         {
             Directory directory = NewDirectory();
@@ -273,7 +273,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestThreeFieldsMixed()
         {
             Directory directory = NewDirectory();
@@ -318,7 +318,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestThreeFieldsMixed2()
         {
             Directory directory = NewDirectory();
@@ -363,7 +363,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoDocumentsNumeric()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -392,7 +392,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoDocumentsMerged()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -436,7 +436,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBigNumericRange()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -465,7 +465,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBigNumericRange2()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -494,7 +494,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -534,7 +534,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBytesTwoDocumentsMerged()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -580,7 +580,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -620,7 +620,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedBytesTwoDocuments()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -652,7 +652,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedBytesThreeDocuments()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -691,7 +691,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedBytesTwoDocumentsMerged()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -742,7 +742,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedMergeAwayAllValues()
         {
             Directory directory = NewDirectory();
@@ -784,7 +784,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBytesWithNewline()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -810,7 +810,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestMissingSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -843,7 +843,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedTermsEnum()
         {
             Directory directory = NewDirectory();
@@ -916,7 +916,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestEmptySortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -948,7 +948,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestEmptyBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -980,7 +980,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestVeryLargeButLegalBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1009,7 +1009,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestVeryLargeButLegalSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1037,7 +1037,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestCodecUsesOwnBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1065,7 +1065,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestCodecUsesOwnSortedBytes()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1093,7 +1093,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestCodecUsesOwnBytesEachTime()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1128,7 +1128,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestCodecUsesOwnSortedBytesEachTime()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -1166,7 +1166,7 @@ namespace Lucene.Net.Index
         /*
          * Simple test case to show how to use the API
          */
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestDocValuesSimple()
         {
             Directory dir = NewDirectory();
@@ -1211,7 +1211,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestRandomSortedBytes()
         {
             Directory dir = NewDirectory();
@@ -1488,7 +1488,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBooleanNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1498,7 +1498,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestByteNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1508,7 +1508,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestByteMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1518,7 +1518,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestShortNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1528,7 +1528,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestShortMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1538,7 +1538,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestIntNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1548,7 +1548,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestIntMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1558,7 +1558,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestLongNumericsVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1568,7 +1568,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestLongMissingVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1643,7 +1643,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBinaryFixedLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1654,7 +1654,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBinaryVariableLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1788,7 +1788,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedFixedLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1799,7 +1799,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedFixedLengthVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1810,7 +1810,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedVariableLengthVsFieldCache()
         {
             int numIterations = AtLeast(1);
@@ -1820,7 +1820,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedVariableLengthVsStoredFields()
         {
             int numIterations = AtLeast(1);
@@ -1830,7 +1830,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetOneValue()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1858,7 +1858,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1896,7 +1896,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoDocumentsMerged()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1941,7 +1941,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoValues()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -1974,7 +1974,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoValuesUnordered()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2007,7 +2007,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetThreeValuesTwoDocs()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2059,7 +2059,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoDocumentsLastMissing()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2094,7 +2094,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoDocumentsLastMissingMerge()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2131,7 +2131,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoDocumentsFirstMissing()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2167,7 +2167,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTwoDocumentsFirstMissingMerge()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2204,7 +2204,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetMergeAwayAllValues()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2235,7 +2235,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetTermsEnum()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2391,7 +2391,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetFixedLengthVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2403,7 +2403,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetVariableLengthVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2414,7 +2414,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetFixedLengthSingleValuedVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2426,7 +2426,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetVariableLengthSingleValuedVsStoredFields()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2648,7 +2648,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetFixedLengthVsUninvertedField()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2660,7 +2660,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetVariableLengthVsUninvertedField()
         {
             AssumeTrue("Codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -2671,7 +2671,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestGCDCompression()
         {
             int numIterations = AtLeast(1);
@@ -2704,13 +2704,13 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestZeros()
         {
             DoTestNumericsVsStoredFields(0, 0);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestZeroOrMin()
         {
             // try to make GCD compression fail if the format did not anticipate that
@@ -2738,7 +2738,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoNumbersOneMissing()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2769,7 +2769,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoNumbersOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2801,7 +2801,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestThreeNumbersOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2839,7 +2839,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoBytesOneMissing()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2873,7 +2873,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwoBytesOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2908,7 +2908,7 @@ namespace Lucene.Net.Index
             directory.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestThreeBytesOneMissingWithMerging()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -2951,7 +2951,7 @@ namespace Lucene.Net.Index
         }
 
         // LUCENE-4853
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestHugeBinaryValues()
         {
             Analyzer analyzer = new MockAnalyzer(Random());
@@ -3072,7 +3072,7 @@ namespace Lucene.Net.Index
         }
 
         // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestHugeBinaryValueLimit()
         {
             // We only test DVFormats that have a limit
@@ -3157,7 +3157,7 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestThreads()
         {
             Directory dir = NewDirectory();
@@ -3276,7 +3276,7 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Tests dv against stored fields with threads (all types + missing)
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestThreads2()
         {
             AssumeTrue("Codec does not support GetDocsWithField", DefaultCodecSupportsDocsWithField());
@@ -3466,7 +3466,7 @@ namespace Lucene.Net.Index
         }
 
         // LUCENE-5218
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestEmptyBinaryValueOnPageSizes()
         {
             // Test larger and larger power-of-two sized values,

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
index 9a49a6f..d65a88b 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseIndexFileFormatTestCase.cs
@@ -90,7 +90,7 @@ namespace Lucene.Net.Index
         /// <summary>
         /// The purpose of this test is to make sure that bulk merge doesn't accumulate useless data over runs.
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestMergeStability()
         {
             Directory dir = NewDirectory();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
index ffef930..b9dfb8b 100644
--- a/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BasePostingsFormatTestCase.cs
@@ -1245,43 +1245,43 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestDocsOnly()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_ONLY, false);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestDocsAndFreqs()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS, false);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestDocsAndFreqsAndPositions()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, false);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestDocsAndFreqsAndPositionsAndPayloads()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, true);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestDocsAndFreqsAndPositionsAndOffsets()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, false);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
         {
             TestFull(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, true);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestRandom()
         {
             int iters = 5;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
index 2acb5fa..a63eb84 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
@@ -74,7 +74,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestRandomStoredFields()
         {
             Directory dir = NewDirectory();
@@ -190,7 +190,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         // LUCENE-1727: make sure doc fields are stored in order
         public virtual void TestStoredFieldsOrder()
         {
@@ -227,7 +227,7 @@ namespace Lucene.Net.Index
             d.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         // LUCENE-1219
         public virtual void TestBinaryFieldOffsetLength()
         {
@@ -261,7 +261,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestNumericField()
         {
             Directory dir = NewDirectory();
@@ -346,7 +346,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestIndexedBit()
         {
             Directory dir = NewDirectory();
@@ -365,7 +365,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestReadSkip()
         {
             Directory dir = NewDirectory();
@@ -420,7 +420,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test, Timeout(300000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestEmptyDocs()
         {
             Directory dir = NewDirectory();
@@ -449,7 +449,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test, Timeout(300000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         public virtual void TestConcurrentReads()
         {
             Directory dir = NewDirectory();
@@ -564,7 +564,7 @@ namespace Lucene.Net.Index
             return result;
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestWriteReadMerge()
         {
             // get another codec, other than the default: so we are merging segments across different codecs
@@ -670,7 +670,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test, LongRunningTest, Timeout(int.MaxValue)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LongRunningTest, Timeout(int.MaxValue)]
         public virtual void TestBigDocuments()
         {
             // "big" as "much bigger than the chunk size"
@@ -747,7 +747,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBulkMergeWithDeletes()
         {
             int numDocs = AtLeast(200);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
index 5e5b20e..85207ad 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseTermVectorsFormatTestCase.cs
@@ -668,7 +668,7 @@ namespace Lucene.Net.Index
             return (new IndexSearcher(reader)).Search(new TermQuery(new Term("id", id)), 1).ScoreDocs[0].Doc;
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         // only one doc with vectors
         public virtual void TestRareVectors()
         {
@@ -715,7 +715,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestHighFreqs()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 3, 5);
@@ -737,7 +737,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test, LongRunningTest, Timeout(int.MaxValue)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LongRunningTest, Timeout(int.MaxValue)]
         public virtual void TestLotsOfFields()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 500, 10);
@@ -755,7 +755,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test, Timeout(300000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, Timeout(300000)]
         // different options for the same field
         public virtual void TestMixedOptions()
         {
@@ -790,7 +790,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestRandom()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 5, 20);
@@ -817,7 +817,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestMerge()
         {
             RandomDocumentFactory docFactory = new RandomDocumentFactory(this, 5, 20);
@@ -866,7 +866,7 @@ namespace Lucene.Net.Index
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         // run random tests from different threads to make sure the per-thread clones
         // don't share mutable data
         public virtual void TestClone()

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs b/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
index e69ed7c..2cfe630 100644
--- a/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Util/BaseDocIdSetTestCase.cs
@@ -77,7 +77,7 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Test length=0.
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestNoBit()
         {
             BitArray bs = new BitArray(1);
@@ -88,7 +88,7 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Test length=1.
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void Test1Bit()
         {
             BitArray bs = new BitArray(1);
@@ -103,7 +103,7 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Test length=2.
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void Test2Bits()
         {
             BitArray bs = new BitArray(2);
@@ -122,8 +122,8 @@ namespace Lucene.Net.Util
         /// <summary>
         /// Compare the content of the set against a <seealso cref="BitSet"/>.
         /// </summary>
-        // [Test, Timeout(150000)] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
-        //[LongRunningTest]
+        [Test, Timeout(150000)]
+        [LongRunningTest]
         public virtual void TestAgainstBitSet()
         {
             int numBits = TestUtil.NextInt(Random(), 100, 1 << 20);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
index 6d913b5..a66f96c 100644
--- a/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/BlockTerms/TestFixedGapPostingsFormat.cs
@@ -38,68 +38,5 @@ namespace Lucene.Net.Codecs.BlockTerms
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
index d19e11a..d4e1286 100644
--- a/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Bloom/TestBloomPostingsFormat.cs
@@ -35,68 +35,5 @@ namespace Lucene.Net.Codecs.Bloom
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
index cd69092..a0b868b 100644
--- a/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/DiskDv/TestDiskDocValuesFormat.cs
@@ -36,531 +36,5 @@ namespace Lucene.Net.Codecs.DiskDV
                 return codec;
             }
         }
-
-
-        #region BaseCompressingDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestUniqueValuesCompression()
-        {
-            base.TestUniqueValuesCompression();
-        }
-
-        [Test]
-        public override void TestDateCompression()
-        {
-            base.TestDateCompression();
-        }
-
-        [Test]
-        public override void TestSingleBigValueCompression()
-        {
-            base.TestSingleBigValueCompression();
-        }
-
-        #endregion
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
index 26b2684..1cd9e4b 100644
--- a/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/IntBlock/TestFixedIntBlockPostingsFormat.cs
@@ -36,68 +36,5 @@ namespace Lucene.Net.Codecs.IntBlock
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
index c255c90..0b74a74 100644
--- a/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/IntBlock/TestVariableIntBlockPostingsFormat.cs
@@ -41,68 +41,5 @@ namespace Lucene.Net.Codecs.IntBlock
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file


[22/58] [abbrv] lucenenet git commit: HACK: (3rd) Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context.

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
index 2ce76f3..dc18580 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Codecs.Lucene45
 {
     /*
@@ -34,5 +36,530 @@ namespace Lucene.Net.Codecs.Lucene45
                 return Codec_Renamed;
             }
         }
+
+        #region BaseCompressingDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestUniqueValuesCompression()
+        {
+            base.TestUniqueValuesCompression();
+        }
+
+        [Test]
+        public override void TestDateCompression()
+        {
+            base.TestDateCompression();
+        }
+
+        [Test]
+        public override void TestSingleBigValueCompression()
+        {
+            base.TestSingleBigValueCompression();
+        }
+
+        #endregion
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
index bf0a5fe..cbf656c 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
@@ -153,5 +153,506 @@ namespace Lucene.Net.Codecs.Perfield
                 }
             }
         }
+
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
index d2275e8..05751f9 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
@@ -45,5 +45,56 @@ namespace Lucene.Net.Codecs.Perfield
             //LUCENE TO-DO
             AssumeTrue("The MockRandom PF randomizes content on the fly, so we can't check it", false);
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs b/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
index 70ee586..628ddc0 100644
--- a/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Index
 {
     /*
@@ -39,5 +41,506 @@ namespace Lucene.Net.Index
         {
             return TestUtil.FieldSupportsHugeBinaryDocValues(field);
         }
+
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs b/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
index e99678b..921b719 100644
--- a/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Index
 {
     /*
@@ -23,5 +25,18 @@ namespace Lucene.Net.Index
         {
             return NewLogMergePolicy(Random());
         }
+
+        #region BaseMergePolicyTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestForceMergeNotNeeded()
+        {
+            base.TestForceMergeNotNeeded();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs b/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
index 7f425f7..c48b98f 100644
--- a/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
@@ -1527,7 +1527,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test]
+        [Test, Timeout(120000)]
         public virtual void TestTonsOfUpdates()
         {
             // LUCENE-5248: make sure that when there are many updates, we don't use too much RAM

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs b/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
index 70c47cc..7d49c1b 100644
--- a/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
@@ -208,5 +208,55 @@ namespace Lucene.Net.Index
             Assert.AreEqual(0, psdp.SnapshotCount, "Should have no snapshots !");
             dir.Dispose();
         }
+
+
+        #region TestSnapshotDeletionPolicy
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestSnapshotDeletionPolicy_Mem()
+        {
+            base.TestSnapshotDeletionPolicy_Mem();
+        }
+
+        [Test]
+        public override void TestBasicSnapshots()
+        {
+            base.TestBasicSnapshots();
+        }
+
+        [Test]
+        public override void TestMultiThreadedSnapshotting()
+        {
+            base.TestMultiThreadedSnapshotting();
+        }
+
+        [Test]
+        public override void TestRollbackToOldSnapshot()
+        {
+            base.TestRollbackToOldSnapshot();
+        }
+
+        [Test]
+        public override void TestReleaseSnapshot()
+        {
+            base.TestReleaseSnapshot();
+        }
+
+        [Test]
+        public override void TestSnapshotLastCommitTwice()
+        {
+            base.TestSnapshotLastCommitTwice();
+        }
+
+        [Test]
+        public override void TestMissingCommits()
+        {
+            base.TestMissingCommits();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs b/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
index 427aa96..20c6b07 100644
--- a/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
@@ -41,5 +41,55 @@ namespace Lucene.Net.Index
         {
             AssumeTrue("The MockRandom PF randomizes content on the fly, so we can't check it", false);
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
index 902db7f..31ed10c 100644
--- a/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
@@ -47,5 +47,88 @@ namespace Lucene.Net.Index
             // and merge into newly formed 3.x segments.
             base.TestWriteReadMerge();
         }
+
+
+        #region BaseStoredFieldsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestRandomStoredFields()
+        {
+            base.TestRandomStoredFields();
+        }
+
+        [Test]
+        // LUCENE-1727: make sure doc fields are stored in order
+        public override void TestStoredFieldsOrder()
+        {
+            base.TestStoredFieldsOrder();
+        }
+
+        [Test]
+        // LUCENE-1219
+        public override void TestBinaryFieldOffsetLength()
+        {
+            base.TestBinaryFieldOffsetLength();
+        }
+
+        [Test]
+        public override void TestNumericField()
+        {
+            base.TestNumericField();
+        }
+
+        [Test]
+        public override void TestIndexedBit()
+        {
+            base.TestIndexedBit();
+        }
+
+        [Test]
+        public override void TestReadSkip()
+        {
+            base.TestReadSkip();
+        }
+
+        [Test]
+        public override void TestEmptyDocs()
+        {
+            base.TestEmptyDocs();
+        }
+
+        [Test]
+        public override void TestConcurrentReads()
+        {
+            base.TestConcurrentReads();
+        }
+
+        [Test, Timeout(120000)]
+        public override void TestBigDocuments()
+        {
+            base.TestBigDocuments();
+        }
+
+        [Test]
+        public override void TestBulkMergeWithDeletes()
+        {
+            base.TestBulkMergeWithDeletes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
index 38f08d4..dac8fa8 100644
--- a/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
@@ -58,5 +58,60 @@ namespace Lucene.Net.Index
         {
             AssumeTrue("The MockRandom PF randomizes content on the fly, so we can't check it", false);
         }
+
+
+
+        #region BaseTermVectorsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        // only one doc with vectors
+        public override void TestRareVectors()
+        {
+            base.TestRareVectors();
+        }
+
+        [Test]
+        public override void TestHighFreqs()
+        {
+            base.TestHighFreqs();
+        }
+
+        [Test]
+        public override void TestLotsOfFields()
+        {
+            base.TestLotsOfFields();
+        }
+
+        [Test]
+        // different options for the same field
+        public override void TestMixedOptions()
+        {
+            base.TestMixedOptions();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestMerge()
+        {
+            base.TestMerge();
+        }
+
+        [Test]
+        // run random tests from different threads to make sure the per-thread clones
+        // don't share mutable data
+        public override void TestClone()
+        {
+            base.TestClone();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs b/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
index 922551c..ede9691 100644
--- a/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
@@ -273,5 +273,19 @@ namespace Lucene.Net.Index
 
             // TODO: Add more checks for other non-double setters!
         }
+
+
+        #region BaseMergePolicyTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestForceMergeNotNeeded()
+        {
+            base.TestForceMergeNotNeeded();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs b/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
index 96ec2f4..16a6d17 100644
--- a/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
+++ b/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
@@ -192,7 +192,7 @@ namespace Lucene.Net.Search
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestPad()
         {
             int[] tests = new int[] { -9999999, -99560, -100, -3, -1, 0, 3, 9, 10, 1000, 999999999 };

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
index 735dc0c..307c51f 100644
--- a/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
+++ b/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
@@ -33,5 +33,219 @@ namespace Lucene.Net.Search.Spans
         {
             CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
         }
+
+
+        #region TestSpanExplanations
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestST1()
+        {
+            base.TestST1();
+        }
+
+        [Test]
+        public override void TestST2()
+        {
+            base.TestST2();
+        }
+
+        [Test]
+        public override void TestST4()
+        {
+            base.TestST4();
+        }
+
+        [Test]
+        public override void TestST5()
+        {
+            base.TestST5();
+        }
+
+        /* some SpanFirstQueries */
+
+        [Test]
+        public override void TestSF1()
+        {
+            base.TestSF1();
+        }
+
+        [Test]
+        public override void TestSF2()
+        {
+            base.TestSF2();
+        }
+
+        [Test]
+        public override void TestSF4()
+        {
+            base.TestSF4();
+        }
+
+        [Test]
+        public override void TestSF5()
+        {
+            base.TestSF5();
+        }
+
+        [Test]
+        public override void TestSF6()
+        {
+            base.TestSF6();
+        }
+
+        /* some SpanOrQueries */
+
+        [Test]
+        public override void TestSO1()
+        {
+            base.TestSO1();
+        }
+
+        [Test]
+        public override void TestSO2()
+        {
+            base.TestSO2();
+        }
+
+        [Test]
+        public override void TestSO3()
+        {
+            base.TestSO3();
+        }
+
+        [Test]
+        public override void TestSO4()
+        {
+            base.TestSO4();
+        }
+
+        /* some SpanNearQueries */
+
+        [Test]
+        public override void TestSNear1()
+        {
+            base.TestSNear1();
+        }
+
+        [Test]
+        public override void TestSNear2()
+        {
+            base.TestSNear2();
+        }
+
+        [Test]
+        public override void TestSNear3()
+        {
+            base.TestSNear3();
+        }
+
+        [Test]
+        public override void TestSNear4()
+        {
+            base.TestSNear4();
+        }
+
+        [Test]
+        public override void TestSNear5()
+        {
+            base.TestSNear5();
+        }
+
+        [Test]
+        public override void TestSNear6()
+        {
+            base.TestSNear6();
+        }
+
+        [Test]
+        public override void TestSNear7()
+        {
+            base.TestSNear7();
+        }
+
+        [Test]
+        public override void TestSNear8()
+        {
+            base.TestSNear8();
+        }
+
+        [Test]
+        public override void TestSNear9()
+        {
+            base.TestSNear9();
+        }
+
+        [Test]
+        public override void TestSNear10()
+        {
+            base.TestSNear10();
+        }
+
+        [Test]
+        public override void TestSNear11()
+        {
+            base.TestSNear11();
+        }
+
+        /* some SpanNotQueries */
+
+        [Test]
+        public override void TestSNot1()
+        {
+            base.TestSNot1();
+        }
+
+        [Test]
+        public override void TestSNot2()
+        {
+            base.TestSNot2();
+        }
+
+        [Test]
+        public override void TestSNot4()
+        {
+            base.TestSNot4();
+        }
+
+        [Test]
+        public override void TestSNot5()
+        {
+            base.TestSNot5();
+        }
+
+        [Test]
+        public override void TestSNot7()
+        {
+            base.TestSNot7();
+        }
+
+        [Test]
+        public override void TestSNot10()
+        {
+            base.TestSNot10();
+        }
+
+        #endregion
+
+        #region TestExplanations
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+
+        /// <summary>
+        /// Placeholder: JUnit freaks if you don't have one test ... making
+        /// class abstract doesn't help
+        /// </summary>
+        [Test]
+        public override void TestNoop()
+        {
+            base.TestNoop();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
index fbfe049..18a2759 100644
--- a/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
@@ -33,5 +33,165 @@ namespace Lucene.Net.Search
         {
             CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
         }
+
+
+        #region TestComplexExplanations
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void Test1()
+        {
+            base.Test1();
+        }
+
+        [Test]
+        public override void Test2()
+        {
+            base.Test2();
+        }
+
+        // :TODO: we really need more crazy complex cases.
+
+        // //////////////////////////////////////////////////////////////////
+
+        // The rest of these aren't that complex, but they are <i>somewhat</i>
+        // complex, and they expose weakness in dealing with queries that match
+        // with scores of 0 wrapped in other queries
+
+        [Test]
+        public override void TestT3()
+        {
+            base.TestT3();
+        }
+
+        [Test]
+        public override void TestMA3()
+        {
+            base.TestMA3();
+        }
+
+        [Test]
+        public override void TestFQ5()
+        {
+            base.TestFQ5();
+        }
+
+        [Test]
+        public override void TestCSQ4()
+        {
+            base.TestCSQ4();
+        }
+
+        [Test]
+        public override void TestDMQ10()
+        {
+            base.TestDMQ10();
+        }
+
+        [Test]
+        public override void TestMPQ7()
+        {
+            base.TestMPQ7();
+        }
+
+        [Test]
+        public override void TestBQ12()
+        {
+            base.TestBQ12();
+        }
+
+        [Test]
+        public override void TestBQ13()
+        {
+            base.TestBQ13();
+        }
+
+        [Test]
+        public override void TestBQ18()
+        {
+            base.TestBQ18();
+        }
+
+        [Test]
+        public override void TestBQ21()
+        {
+            base.TestBQ21();
+        }
+
+        [Test]
+        public override void TestBQ22()
+        {
+            base.TestBQ22();
+        }
+
+        [Test]
+        public override void TestST3()
+        {
+            base.TestST3();
+        }
+
+        [Test]
+        public override void TestST6()
+        {
+            base.TestST6();
+        }
+
+        [Test]
+        public override void TestSF3()
+        {
+            base.TestSF3();
+        }
+
+        [Test]
+        public override void TestSF7()
+        {
+            base.TestSF7();
+        }
+
+        [Test]
+        public override void TestSNot3()
+        {
+            base.TestSNot3();
+        }
+
+        [Test]
+        public override void TestSNot6()
+        {
+            base.TestSNot6();
+        }
+
+        [Test]
+        public override void TestSNot8()
+        {
+            base.TestSNot8();
+        }
+
+        [Test]
+        public override void TestSNot9()
+        {
+            base.TestSNot9();
+        }
+
+        #endregion
+
+        #region TestExplanations
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+
+        /// <summary>
+        /// Placeholder: JUnit freaks if you don't have one test ... making
+        /// class abstract doesn't help
+        /// </summary>
+        [Test]
+        public override void TestNoop()
+        {
+            base.TestNoop();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestExplanations.cs b/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
index a528615..18962f9 100644
--- a/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
@@ -261,7 +261,7 @@ namespace Lucene.Net.Search
         /// Placeholder: JUnit freaks if you don't have one test ... making
         /// class abstract doesn't help
         /// </summary>
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestNoop()
         {
             /* NOOP */

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
index cc0d022..f0e44a8 100644
--- a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
@@ -590,5 +590,19 @@ namespace Lucene.Net.Search
             reader.Dispose();
             dir.Dispose();
         }
+
+
+        #region SorterTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestPad()
+        {
+            base.TestPad();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
index 0fc6843..1b923a3 100644
--- a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
@@ -60,5 +60,22 @@ namespace Lucene.Net.Search
             Assert.IsFalse(a1.Equals(b));
             QueryUtils.Check(a1);
         }
+
+
+
+        #region TestSnapshotDeletionPolicy
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        /// <summary>
+        /// test a bunch of random regular expressions </summary>
+        [Test, Timeout(60000)]
+        public override void TestRegexps()
+        {
+            base.TestRegexps();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs b/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
index f52d360..7f95d2a 100644
--- a/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
@@ -551,5 +551,19 @@ namespace Lucene.Net.Search
             result = search.Search(Csrq("rand", maxRP, null, T, F), null, numDocs).ScoreDocs;
             AssertEquals("max,nul,T,T", 1, result.Length);
         }
+
+
+        #region SorterTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestPad()
+        {
+            base.TestPad();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
index 304a837..5fec12f 100644
--- a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
@@ -927,5 +927,24 @@ namespace Lucene.Net.Search
 
             Qtest(query, new int[] { 0, 1, 2, 3 });
         }
+
+
+        #region TestExplanations
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+
+        /// <summary>
+        /// Placeholder: JUnit freaks if you don't have one test ... making
+        /// class abstract doesn't help
+        /// </summary>
+        [Test]
+        public override void TestNoop()
+        {
+            base.TestNoop();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
index 6b45673..ee990c1 100644
--- a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
@@ -33,5 +33,457 @@ namespace Lucene.Net.Search
         {
             CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
         }
+
+
+        #region TestSimpleExplanations
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestT1()
+        {
+            base.TestT1();
+        }
+
+        [Test]
+        public override void TestT2()
+        {
+            base.TestT2();
+        }
+
+        /* MatchAllDocs */
+
+        [Test]
+        public override void TestMA1()
+        {
+            base.TestMA1();
+        }
+
+        [Test]
+        public override void TestMA2()
+        {
+            base.TestMA2();
+        }
+
+        /* some simple phrase tests */
+
+        [Test]
+        public override void TestP1()
+        {
+            base.TestP1();
+        }
+
+        [Test]
+        public override void TestP2()
+        {
+            base.TestP2();
+        }
+
+        [Test]
+        public override void TestP3()
+        {
+            base.TestP3();
+        }
+
+        [Test]
+        public override void TestP4()
+        {
+            base.TestP4();
+        }
+
+        [Test]
+        public override void TestP5()
+        {
+            base.TestP5();
+        }
+
+        [Test]
+        public override void TestP6()
+        {
+            base.TestP6();
+        }
+
+        [Test]
+        public override void TestP7()
+        {
+            base.TestP7();
+        }
+
+        /* some simple filtered query tests */
+
+        [Test]
+        public override void TestFQ1()
+        {
+            base.TestFQ1();
+        }
+
+        [Test]
+        public override void TestFQ2()
+        {
+            base.TestFQ2();
+        }
+
+        [Test]
+        public override void TestFQ3()
+        {
+            base.TestFQ3();
+        }
+
+        [Test]
+        public override void TestFQ4()
+        {
+            base.TestFQ4();
+        }
+
+        [Test]
+        public override void TestFQ6()
+        {
+            base.TestFQ6();
+        }
+
+        /* ConstantScoreQueries */
+
+        [Test]
+        public override void TestCSQ1()
+        {
+            base.TestCSQ1();
+        }
+
+        [Test]
+        public override void TestCSQ2()
+        {
+            base.TestCSQ2();
+        }
+
+        [Test]
+        public override void TestCSQ3()
+        {
+            base.TestCSQ3();
+        }
+
+        /* DisjunctionMaxQuery */
+
+        [Test]
+        public override void TestDMQ1()
+        {
+            base.TestDMQ1();
+        }
+
+        [Test]
+        public override void TestDMQ2()
+        {
+            base.TestDMQ2();
+        }
+
+        [Test]
+        public override void TestDMQ3()
+        {
+            base.TestDMQ3();
+        }
+
+        [Test]
+        public override void TestDMQ4()
+        {
+            base.TestDMQ4();
+        }
+
+        [Test]
+        public override void TestDMQ5()
+        {
+            base.TestDMQ5();
+        }
+
+        [Test]
+        public override void TestDMQ6()
+        {
+            base.TestDMQ6();
+        }
+
+        [Test]
+        public override void TestDMQ7()
+        {
+            base.TestDMQ7();
+        }
+
+        [Test]
+        public override void TestDMQ8()
+        {
+            base.TestDMQ8();
+        }
+
+        [Test]
+        public override void TestDMQ9()
+        {
+            base.TestDMQ9();
+        }
+
+        /* MultiPhraseQuery */
+
+        [Test]
+        public override void TestMPQ1()
+        {
+            base.TestMPQ1();
+        }
+
+        [Test]
+        public override void TestMPQ2()
+        {
+            base.TestMPQ2();
+        }
+
+        [Test]
+        public override void TestMPQ3()
+        {
+            base.TestMPQ3();
+        }
+
+        [Test]
+        public override void TestMPQ4()
+        {
+            base.TestMPQ4();
+        }
+
+        [Test]
+        public override void TestMPQ5()
+        {
+            base.TestMPQ5();
+        }
+
+        [Test]
+        public override void TestMPQ6()
+        {
+            base.TestMPQ6();
+        }
+
+        /* some simple tests of boolean queries containing term queries */
+
+        [Test]
+        public override void TestBQ1()
+        {
+            base.TestBQ1();
+        }
+
+        [Test]
+        public override void TestBQ2()
+        {
+            base.TestBQ2();
+        }
+
+        [Test]
+        public override void TestBQ3()
+        {
+            base.TestBQ3();
+        }
+
+        [Test]
+        public override void TestBQ4()
+        {
+            base.TestBQ4();
+        }
+
+        [Test]
+        public override void TestBQ5()
+        {
+            base.TestBQ5();
+        }
+
+        [Test]
+        public override void TestBQ6()
+        {
+            base.TestBQ6();
+        }
+
+        [Test]
+        public override void TestBQ7()
+        {
+            base.TestBQ7();
+        }
+
+        [Test]
+        public override void TestBQ8()
+        {
+            base.TestBQ8();
+        }
+
+        [Test]
+        public override void TestBQ9()
+        {
+            base.TestBQ9();
+        }
+
+        [Test]
+        public override void TestBQ10()
+        {
+            base.TestBQ10();
+        }
+
+        [Test]
+        public override void TestBQ11()
+        {
+            base.TestBQ11();
+        }
+
+        [Test]
+        public override void TestBQ14()
+        {
+            base.TestBQ14();
+        }
+
+        [Test]
+        public override void TestBQ15()
+        {
+            base.TestBQ15();
+        }
+
+        [Test]
+        public override void TestBQ16()
+        {
+            base.TestBQ16();
+        }
+
+        [Test]
+        public override void TestBQ17()
+        {
+            base.TestBQ17();
+        }
+
+        [Test]
+        public override void TestBQ19()
+        {
+            base.TestBQ19();
+        }
+
+        [Test]
+        public override void TestBQ20()
+        {
+            base.TestBQ20();
+        }
+
+        /* BQ of TQ: using alt so some fields have zero boost and some don't */
+
+        [Test]
+        public override void TestMultiFieldBQ1()
+        {
+            base.TestMultiFieldBQ1();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ2()
+        {
+            base.TestMultiFieldBQ2();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ3()
+        {
+            base.TestMultiFieldBQ3();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ4()
+        {
+            base.TestMultiFieldBQ4();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ5()
+        {
+            base.TestMultiFieldBQ5();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ6()
+        {
+            base.TestMultiFieldBQ6();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ7()
+        {
+            base.TestMultiFieldBQ7();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ8()
+        {
+            base.TestMultiFieldBQ8();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ9()
+        {
+            base.TestMultiFieldBQ9();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQ10()
+        {
+            base.TestMultiFieldBQ10();
+        }
+
+        /* BQ of PQ: using alt so some fields have zero boost and some don't */
+
+        [Test]
+        public override void TestMultiFieldBQofPQ1()
+        {
+            base.TestMultiFieldBQofPQ1();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQofPQ2()
+        {
+            base.TestMultiFieldBQofPQ2();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQofPQ3()
+        {
+            base.TestMultiFieldBQofPQ3();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQofPQ4()
+        {
+            base.TestMultiFieldBQofPQ4();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQofPQ5()
+        {
+            base.TestMultiFieldBQofPQ5();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQofPQ6()
+        {
+            base.TestMultiFieldBQofPQ6();
+        }
+
+        [Test]
+        public override void TestMultiFieldBQofPQ7()
+        {
+            base.TestMultiFieldBQofPQ7();
+        }
+
+        #endregion
+
+        #region TestExplanations
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+
+        /// <summary>
+        /// Placeholder: JUnit freaks if you don't have one test ... making
+        /// class abstract doesn't help
+        /// </summary>
+        [Test]
+        public override void TestNoop()
+        {
+            base.TestNoop();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs b/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
index bb1c4d0..f8c9fb3 100644
--- a/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
@@ -177,5 +177,19 @@ namespace Lucene.Net.Search
             result = search.Search(q, TermRangeFilter.NewStringRange("rand", maxRP, null, T, F), numDocs).ScoreDocs;
             Assert.AreEqual(1, result.Length, "max,nul,T,T");
         }
+
+
+        #region SorterTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestPad()
+        {
+            base.TestPad();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs b/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
index 73875e2..f103307 100644
--- a/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
+++ b/src/Lucene.Net.Tests/core/Support/TestLinkedHashMap.cs
@@ -355,5 +355,85 @@ namespace Lucene.Net.Support
             dict.Remove(nullTarget);
             Assert.IsFalse(dict.Contains(nullTarget));
         }
+
+
+        #region TestHashMap
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test, LuceneNetSpecific]
+        public override void TestKeyEnumeration()
+        {
+            base.TestKeyEnumeration();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestValueEnumeration()
+        {
+            base.TestValueEnumeration();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestKeyValuePairEnumeration()
+        {
+            base.TestKeyValuePairEnumeration();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestContainsNullKey()
+        {
+            base.TestContainsNullKey();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestContainsKey()
+        {
+            base.TestContainsKey();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestAdd_NoNullKeys_NullValues()
+        {
+            base.TestAdd_NoNullKeys_NullValues();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestAdd_WithNullKeys_NoNullValues()
+        {
+            base.TestAdd_WithNullKeys_NoNullValues();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestGetWithNonExistantKey_EmptyCollection()
+        {
+            base.TestGetWithNonExistantKey_EmptyCollection();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestGetWithNonExistantKey()
+        {
+            base.TestGetWithNonExistantKey();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestAddsUpdate_NotThrowException()
+        {
+            base.TestAddsUpdate_NotThrowException();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestIndexersUpdate_NotThrowException()
+        {
+            base.TestIndexersUpdate_NotThrowException();
+        }
+
+        [Test, LuceneNetSpecific]
+        public override void TestWithValueType()
+        {
+            base.TestWithValueType();
+        }
+
+        #endregion
     }
 }


[30/58] [abbrv] lucenenet git commit: WIP on Grouping

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
new file mode 100644
index 0000000..2a0b307
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -0,0 +1,718 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Queries.Function.ValueSources;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static Lucene.Net.Index.FieldInfo;
+using Lucene.Net.Search.Grouping.Terms;
+using System.Collections;
+using Lucene.Net.Support;
+
+namespace Lucene.Net.Search.Grouping
+{
+    public class AllGroupHeadsCollectorTest : LuceneTestCase
+    {
+        private static readonly DocValuesType_e[] vts = new DocValuesType_e[]{
+            DocValuesType_e.BINARY, DocValuesType_e.SORTED
+        };
+
+        [Test]
+        public void TestBasic()
+        {
+            string groupField = "author";
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                Random(),
+            dir,
+            NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
+
+            // 0
+            Document doc = new Document();
+            AddGroupField(doc, groupField, "author1", canUseIDV, valueType);
+            doc.Add(NewTextField("content", "random text", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "1", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "1", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 1
+            doc = new Document();
+            AddGroupField(doc, groupField, "author1", canUseIDV, valueType);
+            doc.Add(NewTextField("content", "some more random text blob", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "2", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "2", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 2
+            doc = new Document();
+            AddGroupField(doc, groupField, "author1", canUseIDV, valueType);
+            doc.Add(NewTextField("content", "some more random textual data", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "3", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "3", Field.Store.NO));
+            w.AddDocument(doc);
+            w.Commit(); // To ensure a second segment
+
+            // 3
+            doc = new Document();
+            AddGroupField(doc, groupField, "author2", canUseIDV, valueType);
+            doc.Add(NewTextField("content", "some random text", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "4", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "4", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            AddGroupField(doc, groupField, "author3", canUseIDV, valueType);
+            doc.Add(NewTextField("content", "some more random text", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "5", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "5", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 5
+            doc = new Document();
+            AddGroupField(doc, groupField, "author3", canUseIDV, valueType);
+            doc.Add(NewTextField("content", "random blob", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "6", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "6", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 6 -- no author field
+            doc = new Document();
+            doc.Add(NewTextField("content", "random word stuck in alot of other text", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "6", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "6", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 7 -- no author field
+            doc = new Document();
+            doc.Add(NewTextField("content", "random word stuck in alot of other text", Field.Store.NO));
+            doc.Add(NewStringField("id_1", "7", Field.Store.NO));
+            doc.Add(NewStringField("id_2", "7", Field.Store.NO));
+            w.AddDocument(doc);
+
+            IndexReader reader = w.Reader;
+            IndexSearcher indexSearcher = NewSearcher(reader);
+
+            w.Dispose();
+            int maxDoc = reader.MaxDoc;
+
+            Sort sortWithinGroup = new Sort(new SortField("id_1", SortField.Type_e.INT, true));
+            var allGroupHeadsCollector = CreateRandomCollector(groupField, sortWithinGroup, canUseIDV, valueType);
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), allGroupHeadsCollector);
+            assertTrue(ArrayContains(new int[] { 2, 3, 5, 7 }, allGroupHeadsCollector.RetrieveGroupHeads()));
+            assertTrue(OpenBitSetContains(new int[] { 2, 3, 5, 7 }, allGroupHeadsCollector.RetrieveGroupHeads(maxDoc), maxDoc));
+
+            allGroupHeadsCollector = CreateRandomCollector(groupField, sortWithinGroup, canUseIDV, valueType);
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), allGroupHeadsCollector);
+            assertTrue(ArrayContains(new int[] { 2, 3, 4 }, allGroupHeadsCollector.RetrieveGroupHeads()));
+            assertTrue(OpenBitSetContains(new int[] { 2, 3, 4 }, allGroupHeadsCollector.RetrieveGroupHeads(maxDoc), maxDoc));
+
+            allGroupHeadsCollector = CreateRandomCollector(groupField, sortWithinGroup, canUseIDV, valueType);
+            indexSearcher.Search(new TermQuery(new Term("content", "blob")), allGroupHeadsCollector);
+            assertTrue(ArrayContains(new int[] { 1, 5 }, allGroupHeadsCollector.RetrieveGroupHeads()));
+            assertTrue(OpenBitSetContains(new int[] { 1, 5 }, allGroupHeadsCollector.RetrieveGroupHeads(maxDoc), maxDoc));
+
+            // STRING sort type triggers different implementation
+            Sort sortWithinGroup2 = new Sort(new SortField("id_2", SortField.Type_e.STRING, true));
+            allGroupHeadsCollector = CreateRandomCollector(groupField, sortWithinGroup2, canUseIDV, valueType);
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), allGroupHeadsCollector);
+            assertTrue(ArrayContains(new int[] { 2, 3, 5, 7 }, allGroupHeadsCollector.RetrieveGroupHeads()));
+            assertTrue(OpenBitSetContains(new int[] { 2, 3, 5, 7 }, allGroupHeadsCollector.RetrieveGroupHeads(maxDoc), maxDoc));
+
+            Sort sortWithinGroup3 = new Sort(new SortField("id_2", SortField.Type_e.STRING, false));
+            allGroupHeadsCollector = CreateRandomCollector(groupField, sortWithinGroup3, canUseIDV, valueType);
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), allGroupHeadsCollector);
+            // 7 b/c higher doc id wins, even if order of field is in not in reverse.
+            assertTrue(ArrayContains(new int[] { 0, 3, 4, 6 }, allGroupHeadsCollector.RetrieveGroupHeads()));
+            assertTrue(OpenBitSetContains(new int[] { 0, 3, 4, 6 }, allGroupHeadsCollector.RetrieveGroupHeads(maxDoc), maxDoc));
+
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public void TestRandom()
+        {
+            int numberOfRuns = TestUtil.NextInt(Random(), 3, 6);
+            for (int iter = 0; iter < numberOfRuns; iter++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine(string.Format("TEST: iter={0} total={1}", iter, numberOfRuns));
+                }
+
+                int numDocs = TestUtil.NextInt(Random(), 100, 1000) * RANDOM_MULTIPLIER;
+                int numGroups = TestUtil.NextInt(Random(), 1, numDocs);
+
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: numDocs=" + numDocs + " numGroups=" + numGroups);
+                }
+
+                List<BytesRef> groups = new List<BytesRef>();
+                for (int i = 0; i < numGroups; i++)
+                {
+                    string randomValue;
+                    do
+                    {
+                        // B/c of DV based impl we can't see the difference between an empty string and a null value.
+                        // For that reason we don't generate empty string groups.
+                        randomValue = TestUtil.RandomRealisticUnicodeString(Random());
+                    } while ("".equals(randomValue));
+                    groups.Add(new BytesRef(randomValue));
+                }
+                string[] contentStrings = new string[TestUtil.NextInt(Random(), 2, 20)];
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: create fake content");
+                }
+                for (int contentIDX = 0; contentIDX < contentStrings.Length; contentIDX++)
+                {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("real").append(Random().nextInt(3)).append(' ');
+                    int fakeCount = Random().nextInt(10);
+                    for (int fakeIDX = 0; fakeIDX < fakeCount; fakeIDX++)
+                    {
+                        sb.append("fake ");
+                    }
+                    contentStrings[contentIDX] = sb.toString();
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  content=" + sb.toString());
+                    }
+                }
+
+                Directory dir = NewDirectory();
+                RandomIndexWriter w = new RandomIndexWriter(
+                    Random(),
+                    dir,
+                    NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                        new MockAnalyzer(Random())));
+                bool preFlex = "Lucene3x".equals(w.w.Config.Codec.Name);
+                bool canUseIDV = !preFlex;
+                DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
+
+                Document doc = new Document();
+                Document docNoGroup = new Document();
+                Field group = NewStringField("group", "", Field.Store.NO);
+                doc.Add(group);
+                Field valuesField = null;
+                if (canUseIDV)
+                {
+                    switch (valueType)
+                    {
+                        case DocValuesType_e.BINARY:
+                            valuesField = new BinaryDocValuesField("group_dv", new BytesRef());
+                            break;
+                        case DocValuesType_e.SORTED:
+                            valuesField = new SortedDocValuesField("group_dv", new BytesRef());
+                            break;
+                            //default:
+                            //    fail("unhandled type");
+                    }
+                    doc.Add(valuesField);
+                }
+                Field sort1 = NewStringField("sort1", "", Field.Store.NO);
+                doc.Add(sort1);
+                docNoGroup.Add(sort1);
+                Field sort2 = NewStringField("sort2", "", Field.Store.NO);
+                doc.Add(sort2);
+                docNoGroup.Add(sort2);
+                Field sort3 = NewStringField("sort3", "", Field.Store.NO);
+                doc.Add(sort3);
+                docNoGroup.Add(sort3);
+                Field content = NewTextField("content", "", Field.Store.NO);
+                doc.Add(content);
+                docNoGroup.Add(content);
+                IntField id = new IntField("id", 0, Field.Store.NO);
+                doc.Add(id);
+                docNoGroup.Add(id);
+                GroupDoc[] groupDocs = new GroupDoc[numDocs];
+                for (int i = 0; i < numDocs; i++)
+                {
+                    BytesRef groupValue;
+                    if (Random().nextInt(24) == 17)
+                    {
+                        // So we test the "doc doesn't have the group'd
+                        // field" case:
+                        groupValue = null;
+                    }
+                    else
+                    {
+                        groupValue = groups[Random().nextInt(groups.size())];
+                    }
+
+                    GroupDoc groupDoc = new GroupDoc(
+                        i,
+                        groupValue,
+                        groups[Random().nextInt(groups.size())],
+                        groups[Random().nextInt(groups.size())],
+                        new BytesRef(string.Format(CultureInfo.InvariantCulture, "{0:D5}", i)),
+                        contentStrings[Random().nextInt(contentStrings.Length)]
+                    );
+
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  doc content=" + groupDoc.content + " id=" + i + " group=" + (groupDoc.group == null ? "null" : groupDoc.group.Utf8ToString()) + " sort1=" + groupDoc.sort1.Utf8ToString() + " sort2=" + groupDoc.sort2.Utf8ToString() + " sort3=" + groupDoc.sort3.Utf8ToString());
+                    }
+
+                    groupDocs[i] = groupDoc;
+                    if (groupDoc.group != null)
+                    {
+                        group.StringValue = (groupDoc.group.Utf8ToString());
+                        if (canUseIDV)
+                        {
+                            valuesField.BytesValue = (new BytesRef(groupDoc.group.Utf8ToString()));
+                        }
+                    }
+                    sort1.StringValue = (groupDoc.sort1.Utf8ToString());
+                    sort2.StringValue = (groupDoc.sort2.Utf8ToString());
+                    sort3.StringValue = (groupDoc.sort3.Utf8ToString());
+                    content.StringValue = (groupDoc.content);
+                    id.IntValue = (groupDoc.id);
+                    if (groupDoc.group == null)
+                    {
+                        w.AddDocument(docNoGroup);
+                    }
+                    else
+                    {
+                        w.AddDocument(doc);
+                    }
+                }
+
+                DirectoryReader r = w.Reader;
+                w.Dispose();
+
+                // NOTE: intentional but temporary field cache insanity!
+                FieldCache.Ints docIdToFieldId = FieldCache.DEFAULT.GetInts(SlowCompositeReaderWrapper.Wrap(r), "id", false);
+                int[] fieldIdToDocID = new int[numDocs];
+                for (int i = 0; i < numDocs; i++)
+                {
+                    int fieldId = docIdToFieldId.Get(i);
+                    fieldIdToDocID[fieldId] = i;
+                }
+
+                try
+                {
+                    IndexSearcher s = NewSearcher(r);
+                    if (typeof(SlowCompositeReaderWrapper).IsAssignableFrom(s.IndexReader.GetType()))
+                    {
+                        canUseIDV = false;
+                    }
+                    else
+                    {
+                        canUseIDV = !preFlex;
+                    }
+
+                    for (int contentID = 0; contentID < 3; contentID++)
+                    {
+                        ScoreDoc[] hits = s.Search(new TermQuery(new Term("content", "real" + contentID)), numDocs).ScoreDocs;
+                        foreach (ScoreDoc hit in hits)
+                        {
+                            GroupDoc gd = groupDocs[docIdToFieldId.Get(hit.Doc)];
+                            assertTrue(gd.score == 0.0);
+                            gd.score = hit.Score;
+                            int docId = gd.id;
+                            assertEquals(docId, docIdToFieldId.Get(hit.Doc));
+                        }
+                    }
+
+                    foreach (GroupDoc gd in groupDocs)
+                    {
+                        assertTrue(gd.score != 0.0);
+                    }
+
+                    for (int searchIter = 0; searchIter < 100; searchIter++)
+                    {
+
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TEST: searchIter=" + searchIter);
+                        }
+
+                        string searchTerm = "real" + Random().nextInt(3);
+                        bool sortByScoreOnly = Random().nextBoolean();
+                        Sort sortWithinGroup = GetRandomSort(sortByScoreOnly);
+                        var allGroupHeadsCollector = CreateRandomCollector("group", sortWithinGroup, canUseIDV, valueType);
+                        s.Search(new TermQuery(new Term("content", searchTerm)), allGroupHeadsCollector);
+                        int[] expectedGroupHeads = CreateExpectedGroupHeads(searchTerm, groupDocs, sortWithinGroup, sortByScoreOnly, fieldIdToDocID);
+                        int[] actualGroupHeads = allGroupHeadsCollector.RetrieveGroupHeads();
+                        // The actual group heads contains Lucene ids. Need to change them into our id value.
+                        for (int i = 0; i < actualGroupHeads.Length; i++)
+                        {
+                            actualGroupHeads[i] = docIdToFieldId.Get(actualGroupHeads[i]);
+                        }
+                        // Allows us the easily iterate and assert the actual and expected results.
+                        Array.Sort(expectedGroupHeads);
+                        Array.Sort(actualGroupHeads);
+
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("Collector: " + allGroupHeadsCollector.GetType().Name);
+                            Console.WriteLine("Sort within group: " + sortWithinGroup);
+                            Console.WriteLine("Num group: " + numGroups);
+                            Console.WriteLine("Num doc: " + numDocs);
+                            Console.WriteLine("\n=== Expected: \n");
+                            foreach (int expectedDocId in expectedGroupHeads)
+                            {
+                                GroupDoc expectedGroupDoc = groupDocs[expectedDocId];
+                                string expectedGroup = expectedGroupDoc.group == null ? null : expectedGroupDoc.group.Utf8ToString();
+                                Console.WriteLine(
+                                    string.Format(CultureInfo.InvariantCulture,
+                                    "Group:{0,10} score{1:0.0#######,5} Sort1:{2,10} Sort2:{3,10} Sort3:{4,10} doc:{5,10}",
+                                    expectedGroup, expectedGroupDoc.score, expectedGroupDoc.sort1.Utf8ToString(),
+                                    expectedGroupDoc.sort2.Utf8ToString(), expectedGroupDoc.sort3.Utf8ToString(), expectedDocId)
+                                );
+                            }
+                            Console.WriteLine("\n=== Actual: \n");
+                            foreach (int actualDocId in actualGroupHeads)
+                            {
+                                GroupDoc actualGroupDoc = groupDocs[actualDocId];
+                                string actualGroup = actualGroupDoc.group == null ? null : actualGroupDoc.group.Utf8ToString();
+                                Console.WriteLine(
+                                    string.Format(CultureInfo.InvariantCulture,
+                                    "Group:{0,10} score{1:0.0#######,5} Sort1:{2,10} Sort2:{3,10} Sort3:{4,10} doc:{5,10}",
+                                    actualGroup, actualGroupDoc.score, actualGroupDoc.sort1.Utf8ToString(),
+                                    actualGroupDoc.sort2.Utf8ToString(), actualGroupDoc.sort3.Utf8ToString(), actualDocId)
+                                );
+                            }
+                            Console.WriteLine("\n===================================================================================");
+                        }
+
+                        assertArrayEquals(expectedGroupHeads, actualGroupHeads);
+                    }
+                }
+                finally
+                {
+                    QueryUtils.PurgeFieldCache(r);
+                }
+
+                r.Dispose();
+                dir.Dispose();
+            }
+        }
+
+
+        private bool ArrayContains(int[] expected, int[] actual)
+        {
+            Array.Sort(actual); // in some cases the actual docs aren't sorted by docid. This method expects that.
+            if (expected.Length != actual.Length)
+            {
+                return false;
+            }
+
+            foreach (int e in expected)
+            {
+                bool found = false;
+                foreach (int a in actual)
+                {
+                    if (e == a)
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (!found)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private bool OpenBitSetContains(int[] expectedDocs, FixedBitSet actual, int maxDoc)
+        {
+            if (expectedDocs.Length != actual.Cardinality())
+            {
+                return false;
+            }
+
+            FixedBitSet expected = new FixedBitSet(maxDoc);
+            foreach (int expectedDoc in expectedDocs)
+            {
+                expected.Set(expectedDoc);
+            }
+
+            int docId;
+            DocIdSetIterator iterator = expected.GetIterator();
+            while ((docId = iterator.NextDoc()) != DocIdSetIterator.NO_MORE_DOCS)
+            {
+                if (!actual.Get(docId))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private int[] CreateExpectedGroupHeads(string searchTerm, GroupDoc[] groupDocs, Sort docSort, bool sortByScoreOnly, int[] fieldIdToDocID)
+        {
+            IDictionary<BytesRef, List<GroupDoc>> groupHeads = new HashMap<BytesRef, List<GroupDoc>>();
+            foreach (GroupDoc groupDoc in groupDocs)
+            {
+                if (!groupDoc.content.StartsWith(searchTerm))
+                {
+                    continue;
+                }
+
+                if (!groupHeads.ContainsKey(groupDoc.group))
+                {
+                    List<GroupDoc> list = new List<GroupDoc>();
+                    list.Add(groupDoc);
+                    groupHeads[groupDoc.group] = list;
+                    continue;
+                }
+                groupHeads[groupDoc.group].Add(groupDoc);
+            }
+
+            int[] allGroupHeads = new int[groupHeads.Count];
+            int i = 0;
+            foreach (BytesRef groupValue in groupHeads.Keys)
+            {
+                List<GroupDoc> docs = groupHeads[groupValue];
+                docs.Sort(GetComparator(docSort, sortByScoreOnly, fieldIdToDocID));
+                //Collections.Sort(docs, getComparator(docSort, sortByScoreOnly, fieldIdToDocID));
+                allGroupHeads[i++] = docs[0].id;
+            }
+
+            return allGroupHeads;
+        }
+
+        private Sort GetRandomSort(bool scoreOnly)
+        {
+            List<SortField> sortFields = new List<SortField>();
+            if (Random().nextInt(7) == 2 || scoreOnly)
+            {
+                sortFields.Add(SortField.FIELD_SCORE);
+            }
+            else
+            {
+                if (Random().nextBoolean())
+                {
+                    if (Random().nextBoolean())
+                    {
+                        sortFields.Add(new SortField("sort1", SortField.Type_e.STRING, Random().nextBoolean()));
+                    }
+                    else
+                    {
+                        sortFields.Add(new SortField("sort2", SortField.Type_e.STRING, Random().nextBoolean()));
+                    }
+                }
+                else if (Random().nextBoolean())
+                {
+                    sortFields.Add(new SortField("sort1", SortField.Type_e.STRING, Random().nextBoolean()));
+                    sortFields.Add(new SortField("sort2", SortField.Type_e.STRING, Random().nextBoolean()));
+                }
+            }
+            // Break ties:
+            if (Random().nextBoolean() && !scoreOnly)
+            {
+                sortFields.Add(new SortField("sort3", SortField.Type_e.STRING));
+            }
+            else if (!scoreOnly)
+            {
+                sortFields.Add(new SortField("id", SortField.Type_e.INT));
+            }
+            return new Sort(sortFields.ToArray(/*new SortField[sortFields.size()]*/));
+        }
+
+        internal class ComparatorAnonymousHelper : IComparer<GroupDoc>
+        {
+            private readonly AllGroupHeadsCollectorTest outerInstance;
+            private readonly SortField[] sortFields;
+            private readonly bool sortByScoreOnly;
+            private readonly int[] fieldIdToDocID;
+
+            public ComparatorAnonymousHelper(AllGroupHeadsCollectorTest outerInstance, SortField[] sortFields, bool sortByScoreOnly, int[] fieldIdToDocID)
+            {
+                this.outerInstance = outerInstance;
+                this.sortFields = sortFields;
+                this.sortByScoreOnly = sortByScoreOnly;
+                this.fieldIdToDocID = fieldIdToDocID;
+            }
+
+            public int Compare(GroupDoc d1, GroupDoc d2)
+            {
+                foreach (SortField sf in sortFields)
+                {
+                    int cmp;
+                    if (sf.Type == SortField.Type_e.SCORE)
+                    {
+                        if (d1.score > d2.score)
+                        {
+                            cmp = -1;
+                        }
+                        else if (d1.score < d2.score)
+                        {
+                            cmp = 1;
+                        }
+                        else
+                        {
+                            cmp = sortByScoreOnly ? fieldIdToDocID[d1.id] - fieldIdToDocID[d2.id] : 0;
+                        }
+                    }
+                    else if (sf.Field.equals("sort1"))
+                    {
+                        cmp = d1.sort1.CompareTo(d2.sort1);
+                    }
+                    else if (sf.Field.equals("sort2"))
+                    {
+                        cmp = d1.sort2.CompareTo(d2.sort2);
+                    }
+                    else if (sf.Field.equals("sort3"))
+                    {
+                        cmp = d1.sort3.CompareTo(d2.sort3);
+                    }
+                    else
+                    {
+                        assertEquals(sf.Field, "id");
+                        cmp = d1.id - d2.id;
+                    }
+                    if (cmp != 0)
+                    {
+                        return sf.Reverse ? -cmp : cmp;
+                    }
+                }
+                // Our sort always fully tie breaks:
+                fail();
+                return 0;
+            }
+        }
+
+        private IComparer<GroupDoc> GetComparator(Sort sort, bool sortByScoreOnly, int[] fieldIdToDocID)
+        {
+            SortField[] sortFields = sort.GetSort();
+            return new ComparatorAnonymousHelper(this, sortFields, sortByScoreOnly, fieldIdToDocID);
+            //    return new Comparator<GroupDoc>() {
+            //      @Override
+            //      public int compare(GroupDoc d1, GroupDoc d2)
+            //{
+            //    for (SortField sf : sortFields)
+            //    {
+            //        final int cmp;
+            //        if (sf.getType() == SortField.Type.SCORE)
+            //        {
+            //            if (d1.score > d2.score)
+            //            {
+            //                cmp = -1;
+            //            }
+            //            else if (d1.score < d2.score)
+            //            {
+            //                cmp = 1;
+            //            }
+            //            else
+            //            {
+            //                cmp = sortByScoreOnly ? fieldIdToDocID[d1.id] - fieldIdToDocID[d2.id] : 0;
+            //            }
+            //        }
+            //        else if (sf.getField().equals("sort1"))
+            //        {
+            //            cmp = d1.sort1.compareTo(d2.sort1);
+            //        }
+            //        else if (sf.getField().equals("sort2"))
+            //        {
+            //            cmp = d1.sort2.compareTo(d2.sort2);
+            //        }
+            //        else if (sf.getField().equals("sort3"))
+            //        {
+            //            cmp = d1.sort3.compareTo(d2.sort3);
+            //        }
+            //        else
+            //        {
+            //            assertEquals(sf.getField(), "id");
+            //            cmp = d1.id - d2.id;
+            //        }
+            //        if (cmp != 0)
+            //        {
+            //            return sf.getReverse() ? -cmp : cmp;
+            //        }
+            //    }
+            //    // Our sort always fully tie breaks:
+            //    fail();
+            //    return 0;
+            //}
+            //    };
+        }
+
+        private AbstractAllGroupHeadsCollector CreateRandomCollector(string groupField, Sort sortWithinGroup, bool canUseIDV, DocValuesType_e valueType)
+        {
+            AbstractAllGroupHeadsCollector collector;
+            if (Random().nextBoolean())
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                collector = new FunctionAllGroupHeadsCollector(vs, new Hashtable(), sortWithinGroup);
+            }
+            else
+            {
+                collector = TermAllGroupHeadsCollector.Create(groupField, sortWithinGroup);
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("Selected implementation: " + collector.GetType().Name);
+            }
+
+            return collector;
+        }
+
+        private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV, DocValuesType_e valueType)
+        {
+            doc.Add(new TextField(groupField, value, Field.Store.YES));
+            if (canUseIDV)
+            {
+                Field valuesField = null;
+                switch (valueType)
+                {
+                    case DocValuesType_e.BINARY:
+                        valuesField = new BinaryDocValuesField(groupField + "_dv", new BytesRef(value));
+                        break;
+                    case DocValuesType_e.SORTED:
+                        valuesField = new SortedDocValuesField(groupField + "_dv", new BytesRef(value));
+                        break;
+                        //default:
+                        //    fail("unhandled type");
+                }
+                doc.Add(valuesField);
+            }
+        }
+
+        internal class GroupDoc
+        {
+            internal readonly int id;
+            internal readonly BytesRef group;
+            internal readonly BytesRef sort1;
+            internal readonly BytesRef sort2;
+            internal readonly BytesRef sort3;
+            // content must be "realN ..."
+            internal readonly string content;
+            internal float score;
+
+            public GroupDoc(int id, BytesRef group, BytesRef sort1, BytesRef sort2, BytesRef sort3, String content)
+            {
+                this.id = id;
+                this.group = group;
+                this.sort1 = sort1;
+                this.sort2 = sort2;
+                this.sort3 = sort3;
+                this.content = content;
+            }
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
new file mode 100644
index 0000000..c76a4da
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
@@ -0,0 +1,138 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Queries.Function.ValueSources;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Collections;
+using Lucene.Net.Search.Grouping.Terms;
+
+namespace Lucene.Net.Search.Grouping
+{
+    public class AllGroupsCollectorTest : LuceneTestCase
+    {
+        [Test]
+        public void TestTotalGroupCount()
+        {
+
+            string groupField = "author";
+            FieldType customType = new FieldType();
+            customType.Stored = true;
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                Random(),
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+
+            // 0
+            Document doc = new Document();
+            AddGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "random text", Field.Store.YES));
+            doc.Add(new Field("id", "1", customType));
+            w.AddDocument(doc);
+
+            // 1
+            doc = new Document();
+            AddGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "some more random text blob", Field.Store.YES));
+            doc.Add(new Field("id", "2", customType));
+            w.AddDocument(doc);
+
+            // 2
+            doc = new Document();
+            AddGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "some more random textual data", Field.Store.YES));
+            doc.Add(new Field("id", "3", customType));
+            w.AddDocument(doc);
+            w.Commit(); // To ensure a second segment
+
+            // 3
+            doc = new Document();
+            AddGroupField(doc, groupField, "author2", canUseIDV);
+            doc.Add(new TextField("content", "some random text", Field.Store.YES));
+            doc.Add(new Field("id", "4", customType));
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            AddGroupField(doc, groupField, "author3", canUseIDV);
+            doc.Add(new TextField("content", "some more random text", Field.Store.YES));
+            doc.Add(new Field("id", "5", customType));
+            w.AddDocument(doc);
+
+            // 5
+            doc = new Document();
+            AddGroupField(doc, groupField, "author3", canUseIDV);
+            doc.Add(new TextField("content", "random blob", Field.Store.YES));
+            doc.Add(new Field("id", "6", customType));
+            w.AddDocument(doc);
+
+            // 6 -- no author field
+            doc = new Document();
+            doc.Add(new TextField("content", "random word stuck in alot of other text", Field.Store.YES));
+            doc.Add(new Field("id", "6", customType));
+            w.AddDocument(doc);
+
+            IndexSearcher indexSearcher = NewSearcher(w.Reader);
+            w.Dispose();
+
+            AbstractAllGroupsCollector allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), allGroupsCollector);
+            assertEquals(4, allGroupsCollector.GroupCount);
+
+            allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), allGroupsCollector);
+            assertEquals(3, allGroupsCollector.GroupCount);
+
+            allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
+            indexSearcher.Search(new TermQuery(new Term("content", "blob")), allGroupsCollector);
+            assertEquals(2, allGroupsCollector.GroupCount);
+
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV)
+        {
+            doc.Add(new TextField(groupField, value, Field.Store.YES));
+            if (canUseIDV)
+            {
+                doc.Add(new SortedDocValuesField(groupField, new BytesRef(value)));
+            }
+        }
+
+        private AbstractAllGroupsCollector CreateRandomCollector(string groupField, bool canUseIDV)
+        {
+            AbstractAllGroupsCollector selected;
+            if (Random().nextBoolean())
+            {
+                selected = new TermAllGroupsCollector(groupField);
+            }
+            else
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                selected = new FunctionAllGroupsCollector(vs, new Hashtable());
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("Selected implementation: " + selected.GetType().Name);
+            }
+
+            return selected;
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
new file mode 100644
index 0000000..854050b
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
@@ -0,0 +1,648 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Search.Grouping.Term;
+using Lucene.Net.Index;
+using Lucene.Net.Queries.Function.ValueSources;
+using Lucene.Net.Search;
+using Lucene.Net.Store;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using Lucene.Net.Util.Mutable;
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Lucene.Net.Search.Grouping;
+using Lucene.Net.Search.Grouping.Terms;
+
+namespace Lucene.Net.Search.Grouping
+{
+    public class DistinctValuesCollectorTest : AbstractGroupingTestCase
+    {
+        private readonly static NullComparator nullComparator = new NullComparator();
+
+        private readonly string groupField = "author";
+        private readonly string dvGroupField = "author_dv";
+        private readonly string countField = "publisher";
+        private readonly string dvCountField = "publisher_dv";
+
+        internal class ComparerAnonymousHelper1 : IComparer<AbstractGroupCount<IComparable<object>>>
+        {
+            private readonly DistinctValuesCollectorTest outerInstance;
+
+            public ComparerAnonymousHelper1(DistinctValuesCollectorTest outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public int Compare(AbstractGroupCount<IComparable<object>> groupCount1, AbstractGroupCount<IComparable<object>> groupCount2)
+            {
+                if (groupCount1.groupValue == null)
+                {
+                    if (groupCount2.groupValue == null)
+                    {
+                        return 0;
+                    }
+                    return -1;
+                }
+                else if (groupCount2.groupValue == null)
+                {
+                    return 1;
+                }
+                else
+                {
+                    return groupCount1.groupValue.CompareTo(groupCount2.groupValue);
+                }
+            }
+        }
+
+        [Test]
+        public void TestSimple()
+        {
+            Random random = Random();
+            FieldInfo.DocValuesType_e[] dvTypes = new FieldInfo.DocValuesType_e[]{
+                FieldInfo.DocValuesType_e.NUMERIC,
+                FieldInfo.DocValuesType_e.BINARY,
+                FieldInfo.DocValuesType_e.SORTED,
+            };
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                random,
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(random)).SetMergePolicy(NewLogMergePolicy()));
+            bool canUseDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            FieldInfo.DocValuesType_e? dvType = canUseDV ? dvTypes[random.nextInt(dvTypes.Length)] : (FieldInfo.DocValuesType_e?)null;
+
+            Document doc = new Document();
+            addField(doc, groupField, "1", dvType);
+            addField(doc, countField, "1", dvType);
+            doc.Add(new TextField("content", "random text", Field.Store.NO));
+            doc.Add(new StringField("id", "1", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 1
+            doc = new Document();
+            addField(doc, groupField, "1", dvType);
+            addField(doc, countField, "1", dvType);
+            doc.Add(new TextField("content", "some more random text blob", Field.Store.NO));
+            doc.Add(new StringField("id", "2", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 2
+            doc = new Document();
+            addField(doc, groupField, "1", dvType);
+            addField(doc, countField, "2", dvType);
+            doc.Add(new TextField("content", "some more random textual data", Field.Store.NO));
+            doc.Add(new StringField("id", "3", Field.Store.NO));
+            w.AddDocument(doc);
+            w.Commit(); // To ensure a second segment
+
+            // 3
+            doc = new Document();
+            addField(doc, groupField, "2", dvType);
+            doc.Add(new TextField("content", "some random text", Field.Store.NO));
+            doc.Add(new StringField("id", "4", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            addField(doc, groupField, "3", dvType);
+            addField(doc, countField, "1", dvType);
+            doc.Add(new TextField("content", "some more random text", Field.Store.NO));
+            doc.Add(new StringField("id", "5", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 5
+            doc = new Document();
+            addField(doc, groupField, "3", dvType);
+            addField(doc, countField, "1", dvType);
+            doc.Add(new TextField("content", "random blob", Field.Store.NO));
+            doc.Add(new StringField("id", "6", Field.Store.NO));
+            w.AddDocument(doc);
+
+            // 6 -- no author field
+            doc = new Document();
+            doc.Add(new TextField("content", "random word stuck in alot of other text", Field.Store.YES));
+            addField(doc, countField, "1", dvType);
+            doc.Add(new StringField("id", "6", Field.Store.NO));
+            w.AddDocument(doc);
+
+            IndexSearcher indexSearcher = NewSearcher(w.Reader);
+            w.Dispose();
+
+            var cmp = new ComparerAnonymousHelper1(this);
+
+            //    Comparator<AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>> cmp = new Comparator<AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>>() {
+
+            //      @Override
+            //      public int compare(AbstractDistinctValuesCollector.GroupCount<Comparable<Object>> groupCount1, AbstractDistinctValuesCollector.GroupCount<Comparable<Object>> groupCount2)
+            //    {
+            //        if (groupCount1.groupValue == null)
+            //        {
+            //            if (groupCount2.groupValue == null)
+            //            {
+            //                return 0;
+            //            }
+            //            return -1;
+            //        }
+            //        else if (groupCount2.groupValue == null)
+            //        {
+            //            return 1;
+            //        }
+            //        else
+            //        {
+            //            return groupCount1.groupValue.compareTo(groupCount2.groupValue);
+            //        }
+            //    }
+
+            //};
+
+            // === Search for content:random
+            AbstractFirstPassGroupingCollector<IComparable<object>> firstCollector = createRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), firstCollector);
+            Collector distinctValuesCollector
+                = createDistinctCountCollector(firstCollector, groupField, countField, dvType.GetValueOrDefault());
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), distinctValuesCollector);
+
+            var gcs = distinctValuesCollector.GetGroups();
+            //Collections.sort(gcs, cmp);
+            gcs.Sort(cmp);
+            assertEquals(4, gcs.Count);
+
+            compareNull(gcs[0].groupValue);
+            List<IComparable> countValues = new List<IComparable>(gcs[0].uniqueValues);
+            assertEquals(1, countValues.size());
+            compare("1", countValues[0]);
+
+            compare("1", gcs[1].groupValue);
+            countValues = new List<IComparable>(gcs[1].uniqueValues);
+            //Collections.sort(countValues, nullComparator);
+            countValues.Sort(nullComparator);
+            assertEquals(2, countValues.size());
+            compare("1", countValues[0]);
+            compare("2", countValues[1]);
+
+            compare("2", gcs[2].groupValue);
+            countValues = new List<IComparable>(gcs[2].uniqueValues);
+            assertEquals(1, countValues.size());
+            compareNull(countValues[0]);
+
+            compare("3", gcs[3].groupValue);
+            countValues = new List<IComparable>(gcs[3].uniqueValues);
+            assertEquals(1, countValues.size());
+            compare("1", countValues[0]);
+
+            // === Search for content:some
+            firstCollector = createRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), firstCollector);
+            distinctValuesCollector = createDistinctCountCollector(firstCollector, groupField, countField, dvType);
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), distinctValuesCollector);
+
+            gcs = distinctValuesCollector.getGroups();
+            //Collections.sort(gcs, cmp);
+            gcs.Sort(cmp);
+            assertEquals(3, gcs.Count);
+
+            compare("1", gcs.get(0).groupValue);
+            countValues = new List<IComparable>(gcs[0].uniqueValues);
+            assertEquals(2, countValues.size());
+            //Collections.sort(countValues, nullComparator);
+            countValues.Sort(nullComparator);
+            compare("1", countValues[0]);
+            compare("2", countValues[1]);
+
+            compare("2", gcs[1].groupValue);
+            countValues = new List<IComparable>(gcs[1].uniqueValues);
+            assertEquals(1, countValues.size());
+            compareNull(countValues[0]);
+
+            compare("3", gcs.get(2).groupValue);
+            countValues = new List<IComparable>(gcs.get(2).uniqueValues);
+            assertEquals(1, countValues.size());
+            compare("1", countValues[0]);
+
+            // === Search for content:blob
+            firstCollector = createRandomFirstPassCollector(dvType, new Sort(), groupField, 10);
+            indexSearcher.search(new TermQuery(new Term("content", "blob")), firstCollector);
+            distinctValuesCollector = createDistinctCountCollector(firstCollector, groupField, countField, dvType);
+            indexSearcher.search(new TermQuery(new Term("content", "blob")), distinctValuesCollector);
+
+            gcs = distinctValuesCollector.getGroups();
+            //Collections.sort(gcs, cmp);
+            gcs.Sort(cmp);
+            assertEquals(2, gcs.Count);
+
+            compare("1", gcs[0].groupValue);
+            countValues = new List<IComparable>(gcs[0].uniqueValues);
+            // B/c the only one document matched with blob inside the author 1 group
+            assertEquals(1, countValues.Count);
+            compare("1", countValues[0]);
+
+            compare("3", gcs[1].groupValue);
+            countValues = new List<IComparable>(gcs[1].uniqueValues);
+            assertEquals(1, countValues.Count);
+            compare("1", countValues[0]);
+
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public void testRandom()
+        {
+            Random random = Random();
+            int numberOfRuns = TestUtil.NextInt(random, 3, 6);
+            for (int indexIter = 0; indexIter < numberOfRuns; indexIter++)
+            {
+                IndexContext context = createIndexContext();
+                for (int searchIter = 0; searchIter < 100; searchIter++)
+                {
+                    IndexSearcher searcher = NewSearcher(context.indexReader);
+                    bool useDv = context.dvType != null && random.nextBoolean();
+                    FieldInfo.DocValuesType_e? dvType = useDv ? context.dvType : (FieldInfo.DocValuesType_e?)null;
+                    string term = context.contentStrings[random.nextInt(context.contentStrings.Length)];
+                    Sort groupSort = new Sort(new SortField("id", SortField.Type_e.STRING));
+                    int topN = 1 + random.nextInt(10);
+
+                    List<AbstractGroupCount<IComparable>> expectedResult = createExpectedResult(context, term, groupSort, topN);
+
+                    AbstractFirstPassGroupingCollector < Comparable <?>> firstCollector = createRandomFirstPassCollector(dvType, groupSort, groupField, topN);
+                    searcher.Search(new TermQuery(new Term("content", term)), firstCollector);
+                    AbstractDistinctValuesCollector <? extends AbstractDistinctValuesCollector.GroupCount < Comparable <?>>> distinctValuesCollector
+                        = createDistinctCountCollector(firstCollector, groupField, countField, dvType);
+                    searcher.Search(new TermQuery(new Term("content", term)), distinctValuesCollector);
+
+                    List<AbstractGroupCount<IComparable>> actualResult = (List<AbstractGroupCount<IComparable>>)distinctValuesCollector.Groups;
+
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("Index iter=" + indexIter);
+                        Console.WriteLine("Search iter=" + searchIter);
+                        Console.WriteLine("1st pass collector class name=" + firstCollector.GetType().Name);
+                        Console.WriteLine("2nd pass collector class name=" + distinctValuesCollector.GetType().Name);
+                        Console.WriteLine("Search term=" + term);
+                        Console.WriteLine("DVType=" + dvType);
+                        Console.WriteLine("1st pass groups=" + firstCollector.GetTopGroups(0, false));
+                        Console.WriteLine("Expected:");
+                        printGroups(expectedResult);
+                        Console.WriteLine("Actual:");
+                        printGroups(actualResult);
+                    }
+
+                    assertEquals(expectedResult.Count, actualResult.Count);
+                    for (int i = 0; i < expectedResult.size(); i++)
+                    {
+                        AbstractDistinctValuesCollector.GroupCount < Comparable <?>> expected = expectedResult.get(i);
+                        AbstractDistinctValuesCollector.GroupCount < Comparable <?>> actual = actualResult.get(i);
+                        assertValues(expected.groupValue, actual.groupValue);
+                        assertEquals(expected.uniqueValues.size(), actual.uniqueValues.size());
+                        List < Comparable <?>> expectedUniqueValues = new ArrayList<>(expected.uniqueValues);
+                        Collections.sort(expectedUniqueValues, nullComparator);
+                        List < Comparable <?>> actualUniqueValues = new ArrayList<>(actual.uniqueValues);
+                        Collections.sort(actualUniqueValues, nullComparator);
+                        for (int j = 0; j < expectedUniqueValues.size(); j++)
+                        {
+                            assertValues(expectedUniqueValues.get(j), actualUniqueValues.get(j));
+                        }
+                    }
+                }
+                context.indexReader.Dispose();
+                context.directory.Dispose();
+            }
+        }
+
+        private void printGroups(List<AbstractDistinctValuesCollector.GroupCount<IComparable>> results)
+        {
+            for (int i = 0; i < results.size(); i++)
+            {
+                var group = results[i];
+                object gv = group.groupValue;
+                if (gv is BytesRef)
+                {
+                    Console.WriteLine(i + ": groupValue=" + ((BytesRef)gv).Utf8ToString());
+                }
+                else
+                {
+                    Console.WriteLine(i + ": groupValue=" + gv);
+                }
+                foreach (object o in group.uniqueValues)
+                {
+                    if (o is BytesRef)
+                    {
+                        Console.WriteLine("  " + ((BytesRef)o).Utf8ToString());
+                    }
+                    else
+                    {
+                        Console.WriteLine("  " + o);
+                    }
+                }
+            }
+        }
+
+        private void assertValues(object expected, object actual)
+        {
+            if (expected == null)
+            {
+                compareNull(actual);
+            }
+            else
+            {
+                compare(((BytesRef)expected).Utf8ToString(), actual);
+            }
+        }
+
+        private void compare(string expected, object groupValue)
+        {
+            if (typeof(BytesRef).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertEquals(expected, ((BytesRef)groupValue).Utf8ToString());
+            }
+            else if (typeof(double).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertEquals(double.Parse(expected, CultureInfo.InvariantCulture), groupValue);
+            }
+            else if (typeof(long).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertEquals(long.Parse(expected, CultureInfo.InvariantCulture), groupValue);
+            }
+            else if (typeof(MutableValue).IsAssignableFrom(groupValue.GetType()))
+            {
+                MutableValueStr mutableValue = new MutableValueStr();
+                mutableValue.Value = new BytesRef(expected);
+                assertEquals(mutableValue, groupValue);
+            }
+            else
+            {
+                fail();
+            }
+        }
+
+        private void compareNull(object groupValue)
+        {
+            if (groupValue == null)
+            {
+                return; // term based impl...
+            }
+            // DV based impls..
+            if (typeof(BytesRef).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertEquals("", ((BytesRef)groupValue).Utf8ToString());
+            }
+            else if (typeof(double).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertEquals(0.0d, groupValue);
+            }
+            else if (typeof(long).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertEquals(0L, groupValue);
+                // Function based impl
+            }
+            else if (typeof(MutableValue).IsAssignableFrom(groupValue.GetType()))
+            {
+                assertFalse(((MutableValue)groupValue).Exists);
+            }
+            else
+            {
+                fail();
+            }
+        }
+
+        private void addField(Document doc, string field, string value, FieldInfo.DocValuesType_e? type)
+        {
+            doc.Add(new StringField(field, value, Field.Store.YES));
+            if (type == null)
+            {
+                return;
+            }
+            string dvField = field + "_dv";
+
+            Field valuesField = null;
+            switch (type)
+            {
+                case FieldInfo.DocValuesType_e.NUMERIC:
+                    valuesField = new NumericDocValuesField(dvField, int.Parse(value, CultureInfo.InvariantCulture));
+                    break;
+                case FieldInfo.DocValuesType_e.BINARY:
+                    valuesField = new BinaryDocValuesField(dvField, new BytesRef(value));
+                    break;
+                case FieldInfo.DocValuesType_e.SORTED:
+                    valuesField = new SortedDocValuesField(dvField, new BytesRef(value));
+                    break;
+            }
+            doc.Add(valuesField);
+        }
+
+        private AbstractDistinctValuesCollector<AbstractGroupCount<T>> createDistinctCountCollector<T>(AbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
+                                                                            string groupField,
+                                                                            string countField,
+                                                                            FieldInfo.DocValuesType_e dvType)
+                  where T : IComparable
+        {
+            Random random = Random();
+            ICollection<SearchGroup<T>> searchGroups = firstPassGroupingCollector.GetTopGroups(0, false);
+            if (typeof(FunctionFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
+            {
+                return (AbstractDistinctValuesCollector)new FunctionDistinctValuesCollector(new Hashtable(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), searchGroups as ICollection<SearchGroup<MutableValue>>);
+            }
+            else
+            {
+                return (AbstractDistinctValuesCollector)new TermDistinctValuesCollector(groupField, countField, searchGroups as ICollection<SearchGroup<BytesRef>>);
+            }
+        }
+
+        private AbstractFirstPassGroupingCollector<T> createRandomFirstPassCollector<T>(FieldInfo.DocValuesType_e dvType, Sort groupSort, string groupField, int topNGroups)
+        {
+            Random random = Random();
+            if (dvType != null)
+            {
+                if (random.nextBoolean())
+                {
+                    return (AbstractFirstPassGroupingCollector<T>)new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new Hashtable(), groupSort, topNGroups);
+                }
+                else
+                {
+                    return (AbstractFirstPassGroupingCollector<T>)new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
+                }
+            }
+            else
+            {
+                if (random.nextBoolean())
+                {
+                    return (AbstractFirstPassGroupingCollector<T>)new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new Hashtable(), groupSort, topNGroups);
+                }
+                else
+                {
+                    return (AbstractFirstPassGroupingCollector<T>)new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
+                }
+            }
+        }
+
+        internal class GroupCount : AbstractGroupCount<BytesRef>
+        {
+            internal GroupCount(BytesRef groupValue, ICollection<BytesRef> uniqueValues)
+                : base(groupValue)
+            {
+                this.uniqueValues.UnionWith(uniqueValues);
+            }
+        }
+
+        private List<AbstractGroupCount<IComparable>> createExpectedResult(IndexContext context, string term, Sort groupSort, int topN)
+        {
+
+
+            List<AbstractGroupCount<IComparable>> result = new List<AbstractGroupCount<IComparable>>();
+            IDictionary<string, ISet<string>> groupCounts = context.searchTermToGroupCounts[term];
+            int i = 0;
+            foreach (string group in groupCounts.Keys)
+            {
+                if (topN <= i++)
+                {
+                    break;
+                }
+                ISet<BytesRef> uniqueValues = new HashSet<BytesRef>();
+                foreach (string val in groupCounts[group])
+                {
+                    uniqueValues.Add(val != null ? new BytesRef(val) : null);
+                }
+                result.Add(new GroupCount(group != null ? new BytesRef(group) : (BytesRef)null, uniqueValues));
+            }
+            return result;
+        }
+
+        private IndexContext createIndexContext()
+        {
+            Random random = Random();
+            FieldInfo.DocValuesType_e[] dvTypes = new FieldInfo.DocValuesType_e[]{
+        FieldInfo.DocValuesType_e.BINARY,
+        FieldInfo.DocValuesType_e.SORTED
+    };
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                random,
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                new MockAnalyzer(random)).SetMergePolicy(NewLogMergePolicy())
+              );
+
+            bool canUseDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            FieldInfo.DocValuesType_e? dvType = canUseDV ? dvTypes[random.nextInt(dvTypes.Length)] : (FieldInfo.DocValuesType_e?)null;
+
+            int numDocs = 86 + random.nextInt(1087) * RANDOM_MULTIPLIER;
+            string[] groupValues = new string[numDocs / 5];
+            string[] countValues = new string[numDocs / 10];
+            for (int i = 0; i < groupValues.Length; i++)
+            {
+                groupValues[i] = GenerateRandomNonEmptyString();
+            }
+            for (int i = 0; i < countValues.Length; i++)
+            {
+                countValues[i] = GenerateRandomNonEmptyString();
+            }
+
+            List<string> contentStrings = new List<string>();
+            IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts = new Dictionary<string, IDictionary<string, ISet<string>>>();
+            for (int i = 1; i <= numDocs; i++)
+            {
+                string groupValue = random.nextInt(23) == 14 ? null : groupValues[random.nextInt(groupValues.Length)];
+                string countValue = random.nextInt(21) == 13 ? null : countValues[random.nextInt(countValues.Length)];
+                string content = "random" + random.nextInt(numDocs / 20);
+                //IDictionary<string, ISet<string>> groupToCounts = searchTermToGroupCounts[content];
+                //      if (groupToCounts == null)
+                IDictionary<string, ISet<string>> groupToCounts;
+                if (!searchTermToGroupCounts.TryGetValue(content, out groupToCounts))
+                {
+                    // Groups sort always DOCID asc...
+                    searchTermToGroupCounts[content] = groupToCounts = new LurchTable<string, ISet<string>>(16);
+                    contentStrings.Add(content);
+                }
+
+                //ISet<string> countsVals = groupToCounts.get(groupValue);
+                //if (countsVals == null)
+                ISet<string> countsVals;
+                if (!groupToCounts.TryGetValue(groupValue, out countsVals))
+                {
+                    groupToCounts[groupValue] = countsVals = new HashSet<string>();
+                }
+                countsVals.Add(countValue);
+
+                Document doc = new Document();
+                doc.Add(new StringField("id", string.Format(CultureInfo.InvariantCulture, "{0:D9}", i), Field.Store.YES));
+                if (groupValue != null)
+                {
+                    addField(doc, groupField, groupValue, dvType);
+                }
+                if (countValue != null)
+                {
+                    addField(doc, countField, countValue, dvType);
+                }
+                doc.Add(new TextField("content", content, Field.Store.YES));
+                w.AddDocument(doc);
+            }
+
+            DirectoryReader reader = w.Reader;
+            if (VERBOSE)
+            {
+                for (int docID = 0; docID < reader.MaxDoc; docID++)
+                {
+                    Document doc = reader.Document(docID);
+                    Console.WriteLine("docID=" + docID + " id=" + doc.Get("id") + " content=" + doc.Get("content") + " author=" + doc.Get("author") + " publisher=" + doc.Get("publisher"));
+                }
+            }
+
+            w.Dispose();
+            return new IndexContext(dir, reader, dvType.GetValueOrDefault(), searchTermToGroupCounts, contentStrings.ToArray(/*new String[contentStrings.size()]*/));
+        }
+
+        internal class IndexContext
+        {
+
+            internal readonly Directory directory;
+            internal readonly DirectoryReader indexReader;
+            internal readonly FieldInfo.DocValuesType_e dvType;
+            internal readonly IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts;
+            internal readonly string[] contentStrings;
+
+            internal IndexContext(Directory directory, DirectoryReader indexReader, FieldInfo.DocValuesType_e dvType,
+                         IDictionary<string, IDictionary<string, ISet<string>>> searchTermToGroupCounts, string[] contentStrings)
+            {
+                this.directory = directory;
+                this.indexReader = indexReader;
+                this.dvType = dvType;
+                this.searchTermToGroupCounts = searchTermToGroupCounts;
+                this.contentStrings = contentStrings;
+            }
+        }
+
+        internal class NullComparator : IComparer<IComparable>
+        {
+
+            public int Compare(IComparable a, IComparable b)
+            {
+                if (a == b)
+                {
+                    return 0;
+                }
+                else if (a == null)
+                {
+                    return -1;
+                }
+                else if (b == null)
+                {
+                    return 1;
+                }
+                else
+                {
+                    return a.CompareTo(b);
+                }
+            }
+
+        }
+    }
+}


[42/58] [abbrv] lucenenet git commit: Added CopyTo implementation in LinkedHashMap.KeyCollection and ValueCollection

Posted by ni...@apache.org.
Added CopyTo implementation in LinkedHashMap.KeyCollection and ValueCollection


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

Branch: refs/heads/grouping
Commit: f08a0e8d7059d507bfad62add71ed073904ab6c0
Parents: 7c2c581
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 20:36:05 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:56 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Support/LinkedHashMap.cs | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/f08a0e8d/src/Lucene.Net.Core/Support/LinkedHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/LinkedHashMap.cs b/src/Lucene.Net.Core/Support/LinkedHashMap.cs
index 5ae23ce..bad38b6 100644
--- a/src/Lucene.Net.Core/Support/LinkedHashMap.cs
+++ b/src/Lucene.Net.Core/Support/LinkedHashMap.cs
@@ -345,7 +345,10 @@ namespace Lucene.Net.Support
 
             public void CopyTo(TKey[] array, int arrayIndex)
             {
-                throw new NotImplementedException("Implement this as needed");
+                foreach (var element in outerInstance.list)
+                {
+                    array[arrayIndex++] = element.Key;
+                }
             }
 
             public IEnumerator<TKey> GetEnumerator()
@@ -455,7 +458,10 @@ namespace Lucene.Net.Support
 
             public void CopyTo(TValue[] array, int arrayIndex)
             {
-                throw new NotImplementedException("Implement this as needed");
+                foreach (var element in outerInstance.list)
+                {
+                    array[arrayIndex++] = element.Value;
+                }
             }
 
             public IEnumerator<TValue> GetEnumerator()


[41/58] [abbrv] lucenenet git commit: Implemented IComparable in Core.Util.Mutable.MutableValue, IComparable does not automatically bring it along.

Posted by ni...@apache.org.
Implemented IComparable in Core.Util.Mutable.MutableValue, IComparable<T> does not automatically bring it along.


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

Branch: refs/heads/grouping
Commit: fa5f44047ccf406b17dd49530009007de0367462
Parents: f08a0e8
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 20:37:29 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:56 2016 +0700

----------------------------------------------------------------------
 .../Util/Mutable/MutableValue.cs                | 26 +++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/fa5f4404/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs b/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
index 66334b3..d4f5154 100644
--- a/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
+++ b/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Support;
 using System;
 
 /*
@@ -24,7 +25,7 @@ namespace Lucene.Net.Util.Mutable
     ///
     /// @lucene.internal
     /// </summary>
-    public abstract class MutableValue : IComparable<MutableValue>
+    public abstract class MutableValue : IComparable<MutableValue>, IComparable
     {
         protected MutableValue()
         {
@@ -52,8 +53,27 @@ namespace Lucene.Net.Util.Mutable
                 int c = c1.GetHashCode() - c2.GetHashCode();
                 if (c == 0)
                 {
-                    //c = c1.CanonicalName.CompareTo(c2.CanonicalName);
-                    c = String.Compare(c1.Name, c2.Name, StringComparison.Ordinal);
+                    c = c1.FullName.CompareToOrdinal(c2.FullName);
+                }
+                return c;
+            }
+            return CompareSameType(other);
+        }
+
+
+        // LUCENENET specific implementation, for use with FunctionFirstPassGroupingCollector 
+        // (note that IComparable<T> does not inherit IComparable, so we need to explicitly 
+        // do that here in order to support IComparable)
+        public int CompareTo(object other)
+        {
+            Type c1 = this.GetType();
+            Type c2 = other.GetType();
+            if (c1 != c2)
+            {
+                int c = c1.GetHashCode() - c2.GetHashCode();
+                if (c == 0)
+                {
+                    c = c1.FullName.CompareToOrdinal(c2.FullName);
                 }
                 return c;
             }


[03/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/Wrappers.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/Wrappers.cs b/src/Lucene.Net.Tests/core/Support/C5/Wrappers.cs
new file mode 100644
index 0000000..73ed656
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/Wrappers.cs
@@ -0,0 +1,2338 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace Lucene.Net.Support.C5
+{
+    /// <summary>
+    /// A read-only wrapper class for a generic enumerator
+    /// </summary>
+    [Serializable]
+    public class GuardedEnumerator<T> : IEnumerator<T>
+    {
+        #region Fields
+
+        IEnumerator<T> enumerator;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Create a wrapper around a generic enumerator
+        /// </summary>
+        /// <param name="enumerator">The enumerator to wrap</param>
+        public GuardedEnumerator(IEnumerator<T> enumerator)
+        { this.enumerator = enumerator; }
+
+        #endregion
+
+        #region IEnumerator<T> Members
+
+        /// <summary>
+        /// Move wrapped enumerator to next item, or the first item if
+        /// this is the first call to MoveNext. 
+        /// </summary>
+        /// <returns>True if enumerator is valid now</returns>
+        public bool MoveNext() { return enumerator.MoveNext(); }
+
+
+        /// <summary>
+        /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+        /// </summary>
+        /// <value>The current item of the wrapped enumerator.</value>
+        public T Current { get { return enumerator.Current; } }
+
+        #endregion
+
+        #region IDisposable Members
+
+        //TODO: consider possible danger of calling through to Dispose. 
+        /// <summary>
+        /// Dispose wrapped enumerator.
+        /// </summary>
+        public void Dispose() { enumerator.Dispose(); }
+
+        #endregion
+
+
+        #region IEnumerator Members
+
+        object System.Collections.IEnumerator.Current
+        {
+            get { return enumerator.Current; }
+        }
+
+        void System.Collections.IEnumerator.Reset()
+        {
+            enumerator.Reset();
+        }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper class for a generic enumerable
+    ///
+    /// <i>This is mainly interesting as a base of other guard classes</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedEnumerable<T> : System.Collections.Generic.IEnumerable<T>
+    {
+        #region Fields
+
+        System.Collections.Generic.IEnumerable<T> enumerable;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap an enumerable in a read-only wrapper
+        /// </summary>
+        /// <param name="enumerable">The enumerable to wrap</param>
+        public GuardedEnumerable(System.Collections.Generic.IEnumerable<T> enumerable)
+        { this.enumerable = enumerable; }
+
+        #endregion
+
+        #region System.Collections.Generic.IEnumerable<T> Members
+
+        /// <summary>
+        /// Get an enumerator from the wrapped enumerable
+        /// </summary>
+        /// <returns>The enumerator (itself wrapped)</returns>
+        public IEnumerator<T> GetEnumerator()
+        { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
+
+        #endregion
+
+        #region IEnumerable Members
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        #endregion
+
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper for a generic directed enumerable
+    ///
+    /// <i>This is mainly interesting as a base of other guard classes</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedDirectedEnumerable<T> : GuardedEnumerable<T>, IDirectedEnumerable<T>
+    {
+        #region Fields
+
+        IDirectedEnumerable<T> directedenumerable;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a directed enumerable in a read-only wrapper
+        /// </summary>
+        /// <param name="directedenumerable">the collection to wrap</param>
+        public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
+            : base(directedenumerable)
+        { this.directedenumerable = directedenumerable; }
+
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        /// <summary>
+        /// Get a enumerable that enumerates the wrapped collection in the opposite direction
+        /// </summary>
+        /// <returns>The mirrored enumerable</returns>
+        public IDirectedEnumerable<T> Backwards()
+        { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
+
+
+        /// <summary>
+        /// <code>Forwards</code> if same, else <code>Backwards</code>
+        /// </summary>
+        /// <value>The enumeration direction relative to the original collection.</value>
+        public EnumerationDirection Direction
+        { get { return directedenumerable.Direction; } }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper for an ICollectionValue&lt;T&gt;
+    ///
+    /// <i>This is mainly interesting as a base of other guard classes</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedCollectionValue<T> : GuardedEnumerable<T>, ICollectionValue<T>
+    {
+        #region Events
+        /// <summary>
+        /// The ListenableEvents value of the wrapped collection
+        /// </summary>
+        /// <value></value>
+        public virtual EventTypeEnum ListenableEvents { get { return collectionvalue.ListenableEvents; } }
+
+        /// <summary>
+        /// The ActiveEvents value of the wrapped collection
+        /// </summary>
+        /// <value></value>
+        public virtual EventTypeEnum ActiveEvents { get { return collectionvalue.ActiveEvents; } }
+
+        ProxyEventBlock<T> eventBlock;
+        /// <summary>
+        /// The change event. Will be raised for every change operation on the collection.
+        /// </summary>
+        public event CollectionChangedHandler<T> CollectionChanged
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionChanged += value; }
+            remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
+        }
+
+        /// <summary>
+        /// The change event. Will be raised for every change operation on the collection.
+        /// </summary>
+        public event CollectionClearedHandler<T> CollectionCleared
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionCleared += value; }
+            remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
+        }
+
+        /// <summary>
+        /// The item added  event. Will be raised for every individual addition to the collection.
+        /// </summary>
+        public event ItemsAddedHandler<T> ItemsAdded
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsAdded += value; }
+            remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
+        }
+
+        /// <summary>
+        /// The item added  event. Will be raised for every individual addition to the collection.
+        /// </summary>
+        public event ItemInsertedHandler<T> ItemInserted
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemInserted += value; }
+            remove { if (eventBlock != null) eventBlock.ItemInserted -= value; }
+        }
+
+        /// <summary>
+        /// The item removed event. Will be raised for every individual removal from the collection.
+        /// </summary>
+        public event ItemsRemovedHandler<T> ItemsRemoved
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsRemoved += value; }
+            remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
+        }
+
+        /// <summary>
+        /// The item removed event. Will be raised for every individual removal from the collection.
+        /// </summary>
+        public event ItemRemovedAtHandler<T> ItemRemovedAt
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemRemovedAt += value; }
+            remove { if (eventBlock != null) eventBlock.ItemRemovedAt -= value; }
+        }
+        #endregion
+
+        #region Fields
+
+        ICollectionValue<T> collectionvalue;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
+        /// </summary>
+        /// <param name="collectionvalue">the collection to wrap</param>
+        public GuardedCollectionValue(ICollectionValue<T> collectionvalue)
+            : base(collectionvalue)
+        { this.collectionvalue = collectionvalue; }
+
+        #endregion
+
+        #region ICollection<T> Members
+
+        /// <summary>
+        /// Get the size of the wrapped collection
+        /// </summary>
+        /// <value>The size</value>
+        public virtual bool IsEmpty { get { return collectionvalue.IsEmpty; } }
+
+        /// <summary>
+        /// Get the size of the wrapped collection
+        /// </summary>
+        /// <value>The size</value>
+        public virtual int Count { get { return collectionvalue.Count; } }
+
+        /// <summary>
+        /// The value is symbolic indicating the type of asymptotic complexity
+        /// in terms of the size of this collection (worst-case or amortized as
+        /// relevant).
+        /// </summary>
+        /// <value>A characterization of the speed of the 
+        /// <code>Count</code> property in this collection.</value>
+        public virtual Speed CountSpeed { get { return collectionvalue.CountSpeed; } }
+
+        /// <summary>
+        /// Copy the items of the wrapped collection to an array
+        /// </summary>
+        /// <param name="a">The array</param>
+        /// <param name="i">Starting offset</param>
+        public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); }
+
+        /// <summary>
+        /// Create an array from the items of the wrapped collection
+        /// </summary>
+        /// <returns>The array</returns>
+        public virtual T[] ToArray() { return collectionvalue.ToArray(); }
+
+        /// <summary>
+        /// Apply a delegate to all items of the wrapped enumerable.
+        /// </summary>
+        /// <param name="a">The delegate to apply</param>
+        //TODO: change this to throw an exception?
+        public virtual void Apply(Action<T> a) { collectionvalue.Apply(a); }
+
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in the wrapped enumerable.
+        /// </summary>
+        /// <param name="filter">A filter delegate 
+        /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
+        /// <returns>True is such an item exists</returns>
+        public virtual bool Exists(Func<T, bool> filter) { return collectionvalue.Exists(filter); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="filter"></param>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool Find(Func<T, bool> filter, out T item) { return collectionvalue.Find(filter, out item); }
+
+        /// <summary>
+        /// Check if all items in the wrapped enumerable satisfies a specific predicate.
+        /// </summary>
+        /// <param name="filter">A filter delegate 
+        /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
+        /// <returns>True if all items satisfies the predicate</returns>
+        public virtual bool All(Func<T, bool> filter) { return collectionvalue.All(filter); }
+
+        /// <summary>
+        /// Create an enumerable, enumerating the items of this collection that satisfies 
+        /// a certain condition.
+        /// </summary>
+        /// <param name="filter">The T->bool filter delegate defining the condition</param>
+        /// <returns>The filtered enumerable</returns>
+        public virtual System.Collections.Generic.IEnumerable<T> Filter(Func<T, bool> filter) { return collectionvalue.Filter(filter); }
+
+        /// <summary>
+        /// Choose some item of this collection. 
+        /// </summary>
+        /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+        /// <returns></returns>
+        public virtual T Choose() { return collectionvalue.Choose(); }
+
+        #endregion
+
+        #region IShowable Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="stringbuilder"></param>
+        /// <param name="formatProvider"></param>
+        /// <param name="rest"></param>
+        /// <returns></returns>
+        public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+        {
+            return collectionvalue.Show(stringbuilder, ref rest, formatProvider);
+        }
+        #endregion
+
+        #region IFormattable Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="format"></param>
+        /// <param name="formatProvider"></param>
+        /// <returns></returns>
+        public string ToString(string format, IFormatProvider formatProvider)
+        {
+            return collectionvalue.ToString(format, formatProvider);
+        }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper for a directed collection
+    ///
+    /// <i>This is mainly interesting as a base of other guard classes</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedDirectedCollectionValue<T> : GuardedCollectionValue<T>, IDirectedCollectionValue<T>
+    {
+        #region Fields
+
+        IDirectedCollectionValue<T> directedcollection;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a directed collection in a read-only wrapper
+        /// </summary>
+        /// <param name="directedcollection">the collection to wrap</param>
+        public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection)
+            :
+            base(directedcollection)
+        { this.directedcollection = directedcollection; }
+
+        #endregion
+
+        #region IDirectedCollection<T> Members
+
+        /// <summary>
+        /// Get a collection that enumerates the wrapped collection in the opposite direction
+        /// </summary>
+        /// <returns>The mirrored collection</returns>
+        public virtual IDirectedCollectionValue<T> Backwards()
+        { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="predicate"></param>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool FindLast(Func<T, bool> predicate, out T item) { return directedcollection.FindLast(predicate, out item); }
+
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+        { return Backwards(); }
+
+
+        /// <summary>
+        /// <code>Forwards</code> if same, else <code>Backwards</code>
+        /// </summary>
+        /// <value>The enumeration direction relative to the original collection.</value>
+        public EnumerationDirection Direction
+        { get { return directedcollection.Direction; } }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper for an <see cref="T:C5.ICollection`1"/>,
+    /// <para>
+    /// <i>Suitable for wrapping hash tables, <see cref="T:C5.HashSet`1"/>
+    /// and <see cref="T:C5.HashBag`1"/>  </i></para>
+    /// </summary>
+    [Serializable]
+    public class GuardedCollection<T> : GuardedCollectionValue<T>, ICollection<T>
+    {
+        #region Fields
+
+        ICollection<T> collection;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
+        /// </summary>
+        /// <param name="collection">the collection to wrap</param>
+        public GuardedCollection(ICollection<T> collection)
+            : base(collection)
+        {
+            this.collection = collection;
+        }
+
+        #endregion
+
+        #region ICollection<T> Members
+
+        /// <summary>
+        /// (This is a read-only wrapper)
+        /// </summary>
+        /// <value>True</value>
+        public virtual bool IsReadOnly { get { return true; } }
+
+
+        /// <summary> </summary>
+        /// <value>Speed of wrapped collection</value>
+        public virtual Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual int GetUnsequencedHashCode()
+        { return collection.GetUnsequencedHashCode(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="that"></param>
+        /// <returns></returns>
+        public virtual bool UnsequencedEquals(ICollection<T> that)
+        { return collection.UnsequencedEquals(that); }
+
+
+        /// <summary>
+        /// Check if an item is in the wrapped collection
+        /// </summary>
+        /// <param name="item">The item</param>
+        /// <returns>True if found</returns>
+        public virtual bool Contains(T item) { return collection.Contains(item); }
+
+
+        /// <summary>
+        /// Count the number of times an item appears in the wrapped collection
+        /// </summary>
+        /// <param name="item">The item</param>
+        /// <returns>The number of copies</returns>
+        public virtual int ContainsCount(T item) { return collection.ContainsCount(item); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<T> UniqueItems() { return new GuardedCollectionValue<T>(collection.UniqueItems()); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return new GuardedCollectionValue<KeyValuePair<T, int>>(collection.ItemMultiplicities()); }
+
+        /// <summary>
+        /// Check if all items in the argument is in the wrapped collection
+        /// </summary>
+        /// <param name="items">The items</param>
+        /// <returns>True if so</returns>
+        public virtual bool ContainsAll(System.Collections.Generic.IEnumerable<T> items) { return collection.ContainsAll(items); }
+
+        /// <summary> 
+        /// Search for an item in the wrapped collection
+        /// </summary>
+        /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
+        /// <returns></returns>
+        public virtual bool Find(ref T item) { return collection.Find(ref item); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool FindOrAdd(ref T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool Update(T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public virtual bool Update(T item, out T olditem)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool UpdateOrAdd(T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public virtual bool UpdateOrAdd(T item, out T olditem)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool Remove(T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item">The value to remove.</param>
+        /// <param name="removeditem">The removed value.</param>
+        /// <returns></returns>
+        public virtual bool Remove(T item, out T removeditem)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        public virtual void RemoveAllCopies(T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="items"></param>
+        public virtual void RemoveAll(System.Collections.Generic.IEnumerable<T> items)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        public virtual void Clear()
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="items"></param>
+        public virtual void RetainAll(System.Collections.Generic.IEnumerable<T> items)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// Check  wrapped collection for internal consistency
+        /// </summary>
+        /// <returns>True if check passed</returns>
+        public virtual bool Check() { return collection.Check(); }
+
+        #endregion
+
+        #region IExtensible<T> Members
+
+        /// <summary> </summary>
+        /// <value>False if wrapped collection has set semantics</value>
+        public virtual bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
+
+        //TODO: the equalityComparer should be guarded
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual System.Collections.Generic.IEqualityComparer<T> EqualityComparer { get { return collection.EqualityComparer; } }
+
+        /// <summary>
+        /// By convention this is true for any collection with set semantics.
+        /// </summary>
+        /// <value>True if only one representative of a group of equal items 
+        /// is kept in the collection together with the total count.</value>
+        public virtual bool DuplicatesByCounting { get { return collection.DuplicatesByCounting; } }
+
+
+        /// <summary> </summary>
+        /// <value>True if wrapped collection is empty</value>
+        public override bool IsEmpty { get { return collection.IsEmpty; } }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool Add(T item)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        void System.Collections.Generic.ICollection<T>.Add(T item)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="items"></param>
+        public virtual void AddAll(System.Collections.Generic.IEnumerable<T> items)
+        { throw new ReadOnlyCollectionException(); }
+
+        #endregion
+    }
+
+
+    /// <summary>
+    /// A read-only wrapper for a sequenced collection
+    ///
+    /// <i>This is mainly interesting as a base of other guard classes</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedSequenced<T> : GuardedCollection<T>, ISequenced<T>
+    {
+        #region Fields
+
+        ISequenced<T> sequenced;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a sequenced collection in a read-only wrapper
+        /// </summary>
+        /// <param name="sorted"></param>
+        public GuardedSequenced(ISequenced<T> sorted) : base(sorted) { this.sequenced = sorted; }
+
+        #endregion
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection and return the index of the first one.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R == bool</code>) defining the predicate</param>
+        /// <returns>the index, if found, a negative value else</returns>
+        public int FindIndex(Func<T, bool> predicate)
+        {
+            IIndexed<T> indexed = sequenced as IIndexed<T>;
+            if (indexed != null)
+                return indexed.FindIndex(predicate);
+            int index = 0;
+            foreach (T item in this)
+            {
+                if (predicate(item))
+                    return index;
+                index++;
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection and return the index of the last one.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R == bool</code>) defining the predicate</param>
+        /// <returns>the index, if found, a negative value else</returns>
+        public int FindLastIndex(Func<T, bool> predicate)
+        {
+            IIndexed<T> indexed = sequenced as IIndexed<T>;
+            if (indexed != null)
+                return indexed.FindLastIndex(predicate);
+            int index = Count - 1;
+            foreach (T item in Backwards())
+            {
+                if (predicate(item))
+                    return index;
+                index--;
+            }
+            return -1;
+        }
+
+
+
+        #region ISequenced<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public int GetSequencedHashCode()
+        { return sequenced.GetSequencedHashCode(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="that"></param>
+        /// <returns></returns>
+        public bool SequencedEquals(ISequenced<T> that)
+        { return sequenced.SequencedEquals(that); }
+
+        #endregion
+
+        #region IDirectedCollection<T> Members
+
+        /// <summary>
+        /// Get a collection that enumerates the wrapped collection in the opposite direction
+        /// </summary>
+        /// <returns>The mirrored collection</returns>
+        public virtual IDirectedCollectionValue<T> Backwards()
+        { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="predicate"></param>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public virtual bool FindLast(Func<T, bool> predicate, out T item) { return sequenced.FindLast(predicate, out item); }
+
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+        { return Backwards(); }
+
+
+
+        /// <summary>
+        /// <code>Forwards</code> if same, else <code>Backwards</code>
+        /// </summary>
+        /// <value>The enumeration direction relative to the original collection.</value>
+        public EnumerationDirection Direction
+        { get { return EnumerationDirection.Forwards; } }
+
+        #endregion
+    }
+
+
+    /// <summary>
+    /// A read-only wrapper for a sorted collection
+    ///
+    /// <i>This is mainly interesting as a base of other guard classes</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedSorted<T> : GuardedSequenced<T>, ISorted<T>
+    {
+        #region Fields
+
+        ISorted<T> sorted;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a sorted collection in a read-only wrapper
+        /// </summary>
+        /// <param name="sorted"></param>
+        public GuardedSorted(ISorted<T> sorted) : base(sorted) { this.sorted = sorted; }
+
+        #endregion
+
+        #region ISorted<T> Members
+
+        /// <summary>
+        /// Find the strict predecessor of item in the guarded sorted collection,
+        /// that is, the greatest item in the collection smaller than the item.
+        /// </summary>
+        /// <param name="item">The item to find the predecessor for.</param>
+        /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+        /// <returns>True if item has a predecessor; otherwise false.</returns>
+        public bool TryPredecessor(T item, out T res) { return sorted.TryPredecessor(item, out res); }
+
+
+        /// <summary>
+        /// Find the strict successor of item in the guarded sorted collection,
+        /// that is, the least item in the collection greater than the supplied value.
+        /// </summary>
+        /// <param name="item">The item to find the successor for.</param>
+        /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+        /// <returns>True if item has a successor; otherwise false.</returns>
+        public bool TrySuccessor(T item, out T res) { return sorted.TrySuccessor(item, out res); }
+
+
+        /// <summary>
+        /// Find the weak predecessor of item in the guarded sorted collection,
+        /// that is, the greatest item in the collection smaller than or equal to the item.
+        /// </summary>
+        /// <param name="item">The item to find the weak predecessor for.</param>
+        /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
+        /// <returns>True if item has a weak predecessor; otherwise false.</returns>
+        public bool TryWeakPredecessor(T item, out T res) { return sorted.TryWeakPredecessor(item, out res); }
+
+
+        /// <summary>
+        /// Find the weak successor of item in the sorted collection,
+        /// that is, the least item in the collection greater than or equal to the supplied value.
+        /// </summary>
+        /// <param name="item">The item to find the weak successor for.</param>
+        /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
+        /// <returns>True if item has a weak successor; otherwise false.</returns>
+        public bool TryWeakSuccessor(T item, out T res) { return sorted.TryWeakSuccessor(item, out res); }
+
+
+        /// <summary>
+        /// Find the predecessor of the item in the wrapped sorted collection
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+        /// <param name="item">The item</param>
+        /// <returns>The predecessor</returns>
+        public T Predecessor(T item) { return sorted.Predecessor(item); }
+
+
+        /// <summary>
+        /// Find the Successor of the item in the wrapped sorted collection
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+        /// <param name="item">The item</param>
+        /// <returns>The Successor</returns>
+        public T Successor(T item) { return sorted.Successor(item); }
+
+
+        /// <summary>
+        /// Find the weak predecessor of the item in the wrapped sorted collection
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+        /// <param name="item">The item</param>
+        /// <returns>The weak predecessor</returns>
+        public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
+
+
+        /// <summary>
+        /// Find the weak Successor of the item in the wrapped sorted collection
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+        /// <param name="item">The item</param>
+        /// <returns>The weak Successor</returns>
+        public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
+
+
+        /// <summary>
+        /// Run Cut on the wrapped sorted collection
+        /// </summary>
+        /// <param name="c"></param>
+        /// <param name="low"></param>
+        /// <param name="lval"></param>
+        /// <param name="high"></param>
+        /// <param name="hval"></param>
+        /// <returns></returns>
+        public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
+        { return sorted.Cut(c, out low, out lval, out high, out hval); }
+
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
+
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
+        { return sorted.RangeFromTo(bot, top); }
+
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
+
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <returns></returns>
+        public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="items"></param>
+        public void AddSorted(System.Collections.Generic.IEnumerable<T> items)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="low"></param>
+        public void RemoveRangeFrom(T low)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="low"></param>
+        /// <param name="hi"></param>
+        public void RemoveRangeFromTo(T low, T hi)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="hi"></param>
+        public void RemoveRangeTo(T hi)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        #endregion
+
+        #region IPriorityQueue<T> Members
+
+        /// <summary>
+        /// Find the minimum of the wrapped collection
+        /// </summary>
+        /// <returns>The minimum</returns>
+        public T FindMin() { return sorted.FindMin(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public T DeleteMin()
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// Find the maximum of the wrapped collection
+        /// </summary>
+        /// <returns>The maximum</returns>
+        public T FindMax() { return sorted.FindMax(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public T DeleteMax()
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        //TODO: we should guard the comparer!
+        /// <summary>
+        /// The comparer object supplied at creation time for the underlying collection
+        /// </summary>
+        /// <value>The comparer</value>
+        public System.Collections.Generic.IComparer<T> Comparer { get { return sorted.Comparer; } }
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+        { return Backwards(); }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// Read-only wrapper for indexed sorted collections
+    ///
+    /// <i>Suitable for wrapping TreeSet, TreeBag and SortedArray</i>
+    /// </summary>
+    [Serializable]
+    public class GuardedIndexedSorted<T> : GuardedSorted<T>, IIndexedSorted<T>
+    {
+        #region Fields
+
+        IIndexedSorted<T> indexedsorted;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap an indexed sorted collection in a read-only wrapper
+        /// </summary>
+        /// <param name="list">the indexed sorted collection</param>
+        public GuardedIndexedSorted(IIndexedSorted<T> list)
+            : base(list)
+        { this.indexedsorted = list; }
+
+        #endregion
+
+        #region IIndexedSorted<T> Members
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <returns></returns>
+        public new IDirectedCollectionValue<T> RangeFrom(T bot)
+        { return indexedsorted.RangeFrom(bot); }
+
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
+        { return indexedsorted.RangeFromTo(bot, top); }
+
+
+        /// <summary>
+        /// Get the specified range from the wrapped collection. 
+        /// (The current implementation erroneously does not wrap the result.)
+        /// </summary>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public new IDirectedCollectionValue<T> RangeTo(T top)
+        { return indexedsorted.RangeTo(top); }
+
+
+        /// <summary>
+        /// Report the number of items in the specified range of the wrapped collection
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <returns></returns>
+        public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
+
+
+        /// <summary>
+        /// Report the number of items in the specified range of the wrapped collection
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
+
+
+        /// <summary>
+        /// Report the number of items in the specified range of the wrapped collection
+        /// </summary>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public int CountTo(T top) { return indexedsorted.CountTo(top); }
+
+
+        /// <summary>
+        /// Run FindAll on the wrapped collection with the indicated filter.
+        /// The result will <b>not</b> be read-only.
+        /// </summary>
+        /// <param name="f"></param>
+        /// <returns></returns>
+        public IIndexedSorted<T> FindAll(Func<T, bool> f)
+        { return indexedsorted.FindAll(f); }
+
+
+        /// <summary>
+        /// Run Map on the wrapped collection with the indicated mapper.
+        /// The result will <b>not</b> be read-only.
+        /// </summary>
+        /// <param name="m"></param>
+        /// <param name="c">The comparer to use in the result</param>
+        /// <returns></returns>
+        public IIndexedSorted<V> Map<V>(Func<T, V> m, System.Collections.Generic.IComparer<V> c)
+        { return indexedsorted.Map(m, c); }
+
+        #endregion
+
+        #region IIndexed<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The i'th item of the wrapped sorted collection</value>
+        public T this[int i] { get { return indexedsorted[i]; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual Speed IndexingSpeed { get { return indexedsorted.IndexingSpeed; } }
+
+        /// <summary> </summary>
+        /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
+        public IDirectedCollectionValue<T> this[int start, int end]
+        { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
+
+
+        /// <summary>
+        /// Find the (first) index of an item in the wrapped collection
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
+
+
+        /// <summary>
+        /// Find the last index of an item in the wrapped collection
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="i"></param>
+        /// <returns></returns>
+        public T RemoveAt(int i)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="start"></param>
+        /// <param name="count"></param>
+        public void RemoveInterval(int start, int count)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+        { return Backwards(); }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper for a generic list collection
+    /// <i>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
+    /// <see cref="T:C5.LinkedList`1"/>, 
+    /// <see cref="T:C5.HashedLinkedList`1"/>, 
+    /// <see cref="T:C5.ArrayList`1"/> or
+    /// <see cref="T:C5.HashedArray`1"/>.
+    /// </i>
+    /// </summary>
+    [Serializable]
+    public class GuardedList<T> : GuardedSequenced<T>, IList<T>, System.Collections.Generic.IList<T>
+    {
+        #region Fields
+
+        IList<T> innerlist;
+        GuardedList<T> underlying;
+        bool slidableView = false;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a list in a read-only wrapper.  A list gets wrapped as read-only,
+        /// a list view gets wrapped as read-only and non-slidable.
+        /// </summary>
+        /// <param name="list">The list</param>
+        public GuardedList(IList<T> list)
+            : base(list)
+        {
+            this.innerlist = list;
+            // If wrapping a list view, make innerlist = the view, and make 
+            // underlying = a guarded version of the view's underlying list
+            if (list.Underlying != null)
+                underlying = new GuardedList<T>(list.Underlying, null, false);
+        }
+
+        GuardedList(IList<T> list, GuardedList<T> underlying, bool slidableView)
+            : base(list)
+        {
+            this.innerlist = list; this.underlying = underlying; this.slidableView = slidableView;
+        }
+        #endregion
+
+        #region IList<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The first item of the wrapped list</value>
+        public T First { get { return innerlist.First; } }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The last item of the wrapped list</value>
+        public T Last { get { return innerlist.Last; } }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
+        /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
+        public bool FIFO
+        {
+            get { return innerlist.FIFO; }
+            set { throw new ReadOnlyCollectionException("List is read only"); }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public virtual bool IsFixedSize
+        {
+            get { return true; }
+        }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
+        /// <value>The i'th item of the wrapped list</value>
+        public T this[int i]
+        {
+            get { return innerlist[i]; }
+            set { throw new ReadOnlyCollectionException("List is read only"); }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual Speed IndexingSpeed { get { return innerlist.IndexingSpeed; } }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="index"></param>
+        /// <param name="item"></param>
+        public void Insert(int index, T item)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="pointer"></param>
+        /// <param name="item"></param>
+        public void Insert(IList<T> pointer, T item)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        public void InsertFirst(T item)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        public void InsertLast(T item)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <param name="target"></param>
+        public void InsertBefore(T item, T target)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="item"></param>
+        /// <param name="target"></param>
+        public void InsertAfter(T item, T target)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="i"></param>
+        /// <param name="items"></param>
+        public void InsertAll(int i, System.Collections.Generic.IEnumerable<T> items)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
+        /// </summary>
+        /// <param name="filter">The filter to use</param>
+        /// <returns></returns>
+        public IList<T> FindAll(Func<T, bool> filter) { return innerlist.FindAll(filter); }
+
+
+        /// <summary>
+        /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
+        /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The mapper to use.</param>
+        /// <returns>The mapped list</returns>
+        public IList<V> Map<V>(Func<T, V> mapper) { return innerlist.Map(mapper); }
+
+        /// <summary>
+        /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
+        /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The delegate defining the map.</param>
+        /// <param name="itemequalityComparer">The itemequalityComparer to use for the new list</param>
+        /// <returns>The new list.</returns>
+        public IList<V> Map<V>(Func<T, V> mapper, System.Collections.Generic.IEqualityComparer<V> itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public T Remove() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// Create the indicated view on the wrapped list and wrap it read-only.
+        /// </summary>
+        /// <param name="start"></param>
+        /// <param name="count"></param>
+        /// <returns></returns>
+        public IList<T> View(int start, int count)
+        {
+            IList<T> view = innerlist.View(start, count);
+            return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
+        }
+
+        /// <summary>
+        /// Create the indicated view on the wrapped list and wrap it read-only.
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public IList<T> ViewOf(T item)
+        {
+            IList<T> view = innerlist.ViewOf(item);
+            return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
+        }
+
+        /// <summary>
+        /// Create the indicated view on the wrapped list and wrap it read-only.
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public IList<T> LastViewOf(T item)
+        {
+            IList<T> view = innerlist.LastViewOf(item);
+            return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
+        }
+
+
+        /// <summary>
+        /// </summary>
+        /// <value>The wrapped underlying list of the wrapped view </value>
+        public IList<T> Underlying { get { return underlying; } }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The offset of the wrapped list as a view.</value>
+        public int Offset { get { return innerlist.Offset; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual bool IsValid { get { return innerlist.IsValid; } }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> if this is a wrapped view and not a view that was made on a wrapper</exception>
+        /// <param name="offset"></param>
+        public IList<T> Slide(int offset)
+        {
+            if (slidableView)
+            {
+                innerlist.Slide(offset);
+                return this;
+            }
+            else
+                throw new ReadOnlyCollectionException("List is read only");
+        }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="offset"></param>
+        /// <param name="size"></param>
+        public IList<T> Slide(int offset, int size)
+        {
+            if (slidableView)
+            {
+                innerlist.Slide(offset, size);
+                return this;
+            }
+            else
+                throw new ReadOnlyCollectionException("List is read only");
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="offset"></param>
+        /// <returns></returns>
+        public bool TrySlide(int offset)
+        {
+            if (slidableView)
+                return innerlist.TrySlide(offset);
+            else
+                throw new ReadOnlyCollectionException("List is read only");
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="offset"></param>
+        /// <param name="size"></param>
+        /// <returns></returns>
+        public bool TrySlide(int offset, int size)
+        {
+            if (slidableView)
+                return innerlist.TrySlide(offset, size);
+            else
+                throw new ReadOnlyCollectionException("List is read only");
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="otherView"></param>
+        /// <returns></returns>
+        public IList<T> Span(IList<T> otherView)
+        {
+            GuardedList<T> otherGuardedList = otherView as GuardedList<T>;
+            if (otherGuardedList == null)
+                throw new IncompatibleViewException();
+            IList<T> span = innerlist.Span(otherGuardedList.innerlist);
+            if (span == null)
+                return null;
+            return new GuardedList<T>(span, underlying ?? otherGuardedList.underlying ?? this, true);
+        }
+
+        /// <summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// </summary>
+        public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="start"></param>
+        /// <param name="count"></param>
+        public void Reverse(int start, int count)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// Check if wrapped list is sorted according to the default sorting order
+        /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+        /// </summary>
+        /// <exception cref="NotComparableException">if T is not comparable</exception>
+        /// <returns>True if the list is sorted, else false.</returns>
+        public bool IsSorted() { return innerlist.IsSorted(System.Collections.Generic.Comparer<T>.Default); }
+
+        /// <summary>
+        /// Check if wrapped list is sorted
+        /// </summary>
+        /// <param name="c">The sorting order to use</param>
+        /// <returns>True if sorted</returns>
+        public bool IsSorted(System.Collections.Generic.IComparer<T> c) { return innerlist.IsSorted(c); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        public void Sort()
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="c"></param>
+        public void Sort(System.Collections.Generic.IComparer<T> c)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        public void Shuffle()
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="rnd"></param>
+        public void Shuffle(Random rnd)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+        #endregion
+
+        #region IIndexed<T> Members
+
+        /// <summary> </summary>
+        /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
+        public IDirectedCollectionValue<T> this[int start, int end]
+        { get { return new GuardedDirectedCollectionValue<T>(innerlist[start, end]); } }
+
+
+        /// <summary>
+        /// Find the (first) index of an item in the wrapped collection
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public int IndexOf(T item) { return innerlist.IndexOf(item); }
+
+
+        /// <summary>
+        /// Find the last index of an item in the wrapped collection
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="i"></param>
+        /// <returns></returns>
+        public T RemoveAt(int i)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="start"></param>
+        /// <param name="count"></param>
+        public void RemoveInterval(int start, int count)
+        { throw new ReadOnlyCollectionException("List is read only"); }
+
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+        { return Backwards(); }
+
+        #endregion
+
+        #region IStack<T> Members
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns>-</returns>
+        public void Push(T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns>-</returns>
+        public T Pop()
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        #endregion
+
+        #region IQueue<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns>-</returns>
+        public void Enqueue(T item)
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns>-</returns>
+        public T Dequeue()
+        { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+        #endregion
+
+        #region IDisposable Members
+
+        /// <summary>
+        /// Ignore: this may be called by a foreach or using statement.
+        /// </summary>
+        public void Dispose() { }
+
+        #endregion
+
+        #region System.Collections.Generic.IList<T> Members
+
+        void System.Collections.Generic.IList<T>.RemoveAt(int index)
+        {
+            throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+        }
+
+        void System.Collections.Generic.ICollection<T>.Add(T item)
+        {
+            throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+        }
+
+        #endregion
+
+        #region System.Collections.ICollection Members
+
+        bool System.Collections.ICollection.IsSynchronized
+        {
+            get { return false; }
+        }
+
+        [Obsolete]
+        Object System.Collections.ICollection.SyncRoot
+        {
+            get { return innerlist.SyncRoot; }
+        }
+
+        void System.Collections.ICollection.CopyTo(Array arr, int index)
+        {
+            if (index < 0 || index + Count > arr.Length)
+                throw new ArgumentOutOfRangeException();
+
+            foreach (T item in this)
+                arr.SetValue(item, index++);
+        }
+
+        #endregion
+
+        #region System.Collections.IList Members
+
+        Object System.Collections.IList.this[int index]
+        {
+            get { return this[index]; }
+            set
+            {
+                throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+            }
+        }
+
+        int System.Collections.IList.Add(Object o)
+        {
+            throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+        }
+
+        bool System.Collections.IList.Contains(Object o)
+        {
+            return Contains((T)o);
+        }
+
+        int System.Collections.IList.IndexOf(Object o)
+        {
+            return Math.Max(-1, IndexOf((T)o));
+        }
+
+        void System.Collections.IList.Insert(int index, Object o)
+        {
+            throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+        }
+
+        void System.Collections.IList.Remove(Object o)
+        {
+            throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+        }
+
+        void System.Collections.IList.RemoveAt(int index)
+        {
+            throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+        }
+
+        #endregion
+    }
+
+    /// <summary>
+    /// A read-only wrapper for a generic indexable queue (allows indexing).
+    /// 
+    /// <para>Suitable for wrapping a <see cref="T:C5.CircularQueue`1"/></para>
+    /// </summary>
+    /// <typeparam name="T">The item type.</typeparam>
+    [Serializable]
+    public class GuardedQueue<T> : GuardedDirectedCollectionValue<T>, IQueue<T>
+    {
+        #region Fields
+
+        IQueue<T> queue;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a queue in a read-only wrapper
+        /// </summary>
+        /// <param name="queue">The queue</param>
+        public GuardedQueue(IQueue<T> queue) : base(queue) { this.queue = queue; }
+
+        #endregion
+
+        #region IQueue<T> Members
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public bool AllowsDuplicates { get { return queue.AllowsDuplicates; } }
+
+        /// <summary>
+        /// Index into the wrapped queue
+        /// </summary>
+        /// <param name="i"></param>
+        /// <returns></returns>
+        public T this[int i] { get { return queue[i]; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns>-</returns>
+        public void Enqueue(T item)
+        { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns>-</returns>
+        public T Dequeue()
+        { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
+
+        #endregion
+    }
+
+    /// <summary>
+    /// A read-only wrapper for a dictionary.
+    ///
+    /// <i>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary`2"/></i>
+    /// </summary>
+    [Serializable]
+    public class GuardedDictionary<K, V> : GuardedCollectionValue<KeyValuePair<K, V>>, IDictionary<K, V>
+    {
+        #region Fields
+
+        IDictionary<K, V> dict;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a dictionary in a read-only wrapper
+        /// </summary>
+        /// <param name="dict">the dictionary</param>
+        public GuardedDictionary(IDictionary<K, V> dict) : base(dict) { this.dict = dict; }
+
+        #endregion
+
+        #region IDictionary<K,V> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public System.Collections.Generic.IEqualityComparer<K> EqualityComparer { get { return dict.EqualityComparer; } }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a
+        /// read-only wrapper if used as a setter</exception>
+        /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
+        public V this[K key]
+        {
+            get { return dict[key]; }
+            set { throw new ReadOnlyCollectionException(); }
+        }
+
+        /// <summary>
+        /// (This is a read-only wrapper)
+        /// </summary>
+        /// <value>True</value>
+        public bool IsReadOnly { get { return true; } }
+
+
+        //TODO: guard with a read-only wrapper? Probably so!
+        /// <summary> </summary>
+        /// <value>The collection of keys of the wrapped dictionary</value>
+        public ICollectionValue<K> Keys
+        { get { return dict.Keys; } }
+
+
+        /// <summary> </summary>
+        /// <value>The collection of values of the wrapped dictionary</value>
+        public ICollectionValue<V> Values { get { return dict.Values; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public virtual Func<K, V> Func { get { return delegate (K k) { return this[k]; }; } }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        public void Add(K key, V val)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="items"></param>
+        public void AddAll<L, W>(System.Collections.Generic.IEnumerable<KeyValuePair<L, W>> items)
+            where L : K
+            where W : V
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public bool Remove(K key)
+        { throw new ReadOnlyCollectionException(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        /// <returns></returns>
+        public bool Remove(K key, out V val)
+        { throw new ReadOnlyCollectionException(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        public void Clear()
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public Speed ContainsSpeed { get { return dict.ContainsSpeed; } }
+
+        /// <summary>
+        /// Check if the wrapped dictionary contains a specific key
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <returns>True if it does</returns>
+        public bool Contains(K key) { return dict.Contains(key); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="keys"></param>
+        /// <returns></returns>
+        public bool ContainsAll<H>(System.Collections.Generic.IEnumerable<H> keys) where H : K { return dict.ContainsAll(keys); }
+
+        /// <summary>
+        /// Search for a key in the wrapped dictionary, reporting the value if found
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="val">On exit: the value if found</param>
+        /// <returns>True if found</returns>
+        public bool Find(ref K key, out V val) { return dict.Find(ref key, out val); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        /// <returns></returns>
+        public bool Update(K key, V val)
+        { throw new ReadOnlyCollectionException(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        /// <param name="oldval"></param>
+        /// <returns></returns>
+        public bool Update(K key, V val, out V oldval)
+        { throw new ReadOnlyCollectionException(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        /// <returns></returns>
+        public bool FindOrAdd(K key, ref V val)
+        { throw new ReadOnlyCollectionException(); }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        /// <returns></returns>
+        public bool UpdateOrAdd(K key, V val)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="key"></param>
+        /// <param name="val"></param>
+        /// <param name="oldval"></param>
+        /// <returns></returns>
+        public bool UpdateOrAdd(K key, V val, out V oldval)
+        { throw new ReadOnlyCollectionException(); }
+
+
+        /// <summary>
+        /// Check the internal consistency of the wrapped dictionary
+        /// </summary>
+        /// <returns>True if check passed</returns>
+        public bool Check() { return dict.Check(); }
+
+        #endregion
+    }
+
+
+
+    /// <summary>
+    /// A read-only wrapper for a sorted dictionary.
+    ///
+    /// <i>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary`2"/></i>
+    /// </summary>
+    [Serializable]
+    public class GuardedSortedDictionary<K, V> : GuardedDictionary<K, V>, ISortedDictionary<K, V>
+    {
+        #region Fields
+
+        ISortedDictionary<K, V> sorteddict;
+
+        #endregion
+
+        #region Constructor
+
+        /// <summary>
+        /// Wrap a sorted dictionary in a read-only wrapper
+        /// </summary>
+        /// <param name="sorteddict">the dictionary</param>
+        public GuardedSortedDictionary(ISortedDictionary<K, V> sorteddict)
+            : base(sorteddict)
+        { this.sorteddict = sorteddict; }
+
+        #endregion
+
+        #region ISortedDictionary<K,V> Members
+
+        /// <summary>
+        /// The key comparer used by this dictionary.
+        /// </summary>
+        /// <value></value>
+        public System.Collections.Generic.IComparer<K> Comparer { get { return sorteddict.Comparer; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public new ISorted<K> Keys { get { return null; } }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// predecessor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The predecessor, if any</param>
+        /// <returns>True if key has a predecessor</returns>
+        public bool TryPredecessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sorteddict.TryPredecessor(key, out res);
+        }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// successor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The successor, if any</param>
+        /// <returns>True if the key has a successor</returns>
+        public bool TrySuccessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sorteddict.TrySuccessor(key, out res);
+        }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// weak predecessor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The predecessor, if any</param>
+        /// <returns>True if key has a weak predecessor</returns>
+        public bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sorteddict.TryWeakPredecessor(key, out res);
+        }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// weak successor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The weak successor, if any</param>
+        /// <returns>True if the key has a weak successor</returns>
+        public bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sorteddict.TryWeakSuccessor(key, out res);
+        }
+
+        /// <summary>
+        /// Get the entry in the wrapped dictionary whose key is the
+        /// predecessor of a specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> Predecessor(K key)
+        { return sorteddict.Predecessor(key); }
+
+        /// <summary>
+        /// Get the entry in the wrapped dictionary whose key is the
+        /// successor of a specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> Successor(K key)
+        { return sorteddict.Successor(key); }
+
+
+        /// <summary>
+        /// Get the entry in the wrapped dictionary whose key is the
+        /// weak predecessor of a specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> WeakPredecessor(K key)
+        { return sorteddict.WeakPredecessor(key); }
+
+
+        /// <summary>
+        /// Get the entry in the wrapped dictionary whose key is the
+        /// weak successor of a specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> WeakSuccessor(K key)
+        { return sorteddict.WeakSuccessor(key); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public KeyValuePair<K, V> FindMin()
+        {
+            return sorteddict.FindMin();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public KeyValuePair<K, V> DeleteMin()
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public KeyValuePair<K, V> FindMax()
+        {
+            return sorteddict.FindMax();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <returns></returns>
+        public KeyValuePair<K, V> DeleteMax()
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="c"></param>
+        /// <param name="lowEntry"></param>
+        /// <param name="lowIsValid"></param>
+        /// <param name="highEntry"></param>
+        /// <param name="highIsValid"></param>
+        /// <returns></returns>
+        public bool Cut(IComparable<K> c, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
+        {
+            return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); ;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
+        {
+            return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFrom(bot));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
+        {
+            return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFromTo(bot, top));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
+        {
+            return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeTo(top));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
+        {
+            return new GuardedDirectedCollectionValue<KeyValuePair<K, V>>(sorteddict.RangeAll());
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="items"></param>
+        public void AddSorted(System.Collections.Generic.IEnumerable<KeyValuePair<K, V>> items)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="low"></param>
+        public void RemoveRangeFrom(K low)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="low"></param>
+        /// <param name="hi"></param>
+        public void RemoveRangeFromTo(K low, K hi)
+        { throw new ReadOnlyCollectionException(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrapper</exception>
+        /// <param name="hi"></param>
+        public void RemoveRangeTo(K hi)
+        { throw new ReadOnlyCollectionException(); }
+
+        #endregion
+    }
+
+}
\ No newline at end of file


[12/58] [abbrv] lucenenet git commit: Added unit tests for Core.Support.HashMap

Posted by ni...@apache.org.
Added unit tests for Core.Support.HashMap


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

Branch: refs/heads/grouping
Commit: dc8a4b8e219aea297101eab2b790ffe7d9e6d86d
Parents: a0f684d
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 16:48:05 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Mon Nov 7 18:44:12 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Tests/Lucene.Net.Tests.csproj    |   1 +
 .../core/Support/TestHashMap.cs                 | 127 ++++++++++---------
 2 files changed, 65 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dc8a4b8e/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 e9e98e8..0b0ad11 100644
--- a/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
+++ b/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
@@ -483,6 +483,7 @@
     <Compile Include="core\Support\C5\SupportClasses.cs" />
     <Compile Include="core\Support\C5\WeakViewList.cs" />
     <Compile Include="core\Support\C5\Wrappers.cs" />
+    <Compile Include="core\Support\TestHashMap.cs" />
     <Compile Include="core\Support\TestLongBuffer.cs" />
     <Compile Include="core\Support\TestByteBuffer.cs" />
     <Compile Include="core\Support\TestLurchTable.cs" />

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/dc8a4b8e/src/Lucene.Net.Tests/core/Support/TestHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestHashMap.cs b/src/Lucene.Net.Tests/core/Support/TestHashMap.cs
index 574f020..7707e4c 100644
--- a/src/Lucene.Net.Tests/core/Support/TestHashMap.cs
+++ b/src/Lucene.Net.Tests/core/Support/TestHashMap.cs
@@ -1,39 +1,40 @@
-/*
- *
- * 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.Attributes;
+using NUnit.Framework;
 using System;
 using System.Collections.Generic;
-using NUnit.Framework;
 
 namespace Lucene.Net.Support
 {
+    /*
+     *
+     * 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 TestHashMap
     {
-        private static HashMap<TKey, TValue> GetNewHashMap<TKey, TValue>()
+        protected virtual HashMap<TKey, TValue> GetNewHashMap<TKey, TValue>()
         {
             return new HashMap<TKey, TValue>();
         }
 
-        private static HashMap<string,string> GetDefaultHashMap1()
+        private HashMap<string,string> GetDefaultHashMap1()
         {
             var hm = GetNewHashMap<string, string>();
             hm.Add("key1", "value1");
@@ -41,8 +42,8 @@ namespace Lucene.Net.Support
             return hm;
         }
 
-        [Test]
-        public void TestKeyEnumeration()
+        [Test, LuceneNetSpecific]
+        public virtual void TestKeyEnumeration()
         {
             var keys = new List<string> {"key1", "key2"};
             var dict = GetDefaultHashMap1();
@@ -59,8 +60,8 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test]
-        public void TestValueEnumeration()
+        [Test, LuceneNetSpecific]
+        public virtual void TestValueEnumeration()
         {
             var values = new List<string> { "value1", "value2" };
             var dict = GetDefaultHashMap1();
@@ -77,26 +78,26 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test]
-        public void TestKeyValuePairEnumeration()
+        [Test, LuceneNetSpecific]
+        public virtual void TestKeyValuePairEnumeration()
         {
             var dict = GetDefaultHashMap1();
             Action<KeyValuePair<string, string>> act = kvp =>
-                                                           {
-                                                               Assert.IsNotNull(kvp);
-                                                               if (kvp.Key == "key1")
-                                                               {
-                                                                   Assert.AreEqual("value1", kvp.Value);
-                                                               }
-                                                               else if (kvp.Key == "key2")
-                                                               {
-                                                                   Assert.AreEqual("value2", kvp.Value);
-                                                               }
-                                                               else if (kvp.Key == null)
-                                                               {
-                                                                   Assert.AreEqual("nullval", kvp.Value);
-                                                               }
-                                                           };
+                {
+                    Assert.IsNotNull(kvp);
+                    if (kvp.Key == "key1")
+                    {
+                        Assert.AreEqual("value1", kvp.Value);
+                    }
+                    else if (kvp.Key == "key2")
+                    {
+                        Assert.AreEqual("value2", kvp.Value);
+                    }
+                    else if (kvp.Key == null)
+                    {
+                        Assert.AreEqual("nullval", kvp.Value);
+                    }
+                };
 
             foreach (var kvp in dict)
             {
@@ -110,8 +111,8 @@ namespace Lucene.Net.Support
             }
         }
 
-        [Test]
-        public void TestContainsNullKey()
+        [Test, LuceneNetSpecific]
+        public virtual void TestContainsNullKey()
         {
             var dict = GetDefaultHashMap1();
             Assert.IsFalse(dict.ContainsKey(null));
@@ -122,16 +123,16 @@ namespace Lucene.Net.Support
             Assert.AreEqual("value", dict[null]);
         }
 
-        [Test]
-        public void TestContainsKey()
+        [Test, LuceneNetSpecific]
+        public virtual void TestContainsKey()
         {
             var dict = GetDefaultHashMap1();
             Assert.IsTrue(dict.ContainsKey("key1"));
             Assert.IsTrue(dict.ContainsKey("key2"));
         }
 
-        [Test]
-        public void TestAdd_NoNullKeys_NullValues()
+        [Test, LuceneNetSpecific]
+        public virtual void TestAdd_NoNullKeys_NullValues()
         {
             var dict = GetNewHashMap<string, string>();
             dict.Add("key1", null);
@@ -140,8 +141,8 @@ namespace Lucene.Net.Support
             Assert.AreEqual(2, dict.Count);
         }
 
-        [Test]
-        public void TestAdd_WithNullKeys_NoNullValues()
+        [Test, LuceneNetSpecific]
+        public virtual void TestAdd_WithNullKeys_NoNullValues()
         {
             var dict = GetNewHashMap<string, string>();
             dict.Add("key1", "value1");
@@ -150,24 +151,24 @@ namespace Lucene.Net.Support
             Assert.AreEqual(2, dict.Count);
         }
 
-        [Test]
-        public void TestGetWithNonExistantKey_EmptyCollection()
+        [Test, LuceneNetSpecific]
+        public virtual void TestGetWithNonExistantKey_EmptyCollection()
         {
             var dict = GetNewHashMap<string, string>();
             Assert.IsNull(dict["nothing"]);
             Assert.IsNull(dict[null]);
         }
 
-        [Test]
-        public void TestGetWithNonExistantKey()
+        [Test, LuceneNetSpecific]
+        public virtual void TestGetWithNonExistantKey()
         {
             var dict = GetDefaultHashMap1();
             Assert.IsNull(dict["nothing"]);
             Assert.IsNull(dict[null]);
         }
 
-        [Test]
-        public void TestAddsUpdate_NotThrowException()
+        [Test, LuceneNetSpecific]
+        public virtual void TestAddsUpdate_NotThrowException()
         {
             var dict = GetNewHashMap<string, string>();
 
@@ -180,8 +181,8 @@ namespace Lucene.Net.Support
             Assert.AreEqual(1, dict.Count);
         }
 
-        [Test]
-        public void TestIndexersUpdate_NotThrowException()
+        [Test, LuceneNetSpecific]
+        public virtual void TestIndexersUpdate_NotThrowException()
         {
             var dict = GetNewHashMap<string, string>();
 
@@ -194,8 +195,8 @@ namespace Lucene.Net.Support
             Assert.AreEqual(1, dict.Count);
         }
 
-        [Test]
-        public void TestWithValueType()
+        [Test, LuceneNetSpecific]
+        public virtual void TestWithValueType()
         {
             // Make sure default value types are stored in the internal dictionary
             // and not the _nullValue variable


[10/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Core/Support/C5.Support.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/C5.Support.cs b/src/Lucene.Net.Core/Support/C5.Support.cs
new file mode 100644
index 0000000..9a9fcf6
--- /dev/null
+++ b/src/Lucene.Net.Core/Support/C5.Support.cs
@@ -0,0 +1,7335 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Linq;
+using System.Reflection;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.C5
+{
+    // LUCENENET NOTE: These are support types required by TreeSet{T} and 
+    // TreeDictionary{K, V} (which is similar to TreeMap in Java). These were brought
+    // over from the C5 library. https://github.com/sestoft/C5
+
+    /// <summary>
+    /// Base class for classes implementing ICollectionValue[T]
+    /// </summary>
+    [Serializable]
+    public abstract class CollectionValueBase<T> : EnumerableBase<T>, ICollectionValue<T>, IShowable
+    {
+        #region Event handling
+        EventBlock<T> eventBlock;
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual EventTypeEnum ListenableEvents { get { return 0; } }
+
+        /// <summary>
+        /// A flag bitmap of the events currently subscribed to by this collection.
+        /// </summary>
+        /// <value></value>
+        public virtual EventTypeEnum ActiveEvents { get { return eventBlock == null ? 0 : eventBlock.events; } }
+
+        private void checkWillListen(EventTypeEnum eventType)
+        {
+            if ((ListenableEvents & eventType) == 0)
+                throw new UnlistenableEventException();
+        }
+
+        /// <summary>
+        /// The change event. Will be raised for every change operation on the collection.
+        /// </summary>
+        public virtual event CollectionChangedHandler<T> CollectionChanged
+        {
+            add { checkWillListen(EventTypeEnum.Changed); (eventBlock ?? (eventBlock = new EventBlock<T>())).CollectionChanged += value; }
+            remove
+            {
+                checkWillListen(EventTypeEnum.Changed);
+                if (eventBlock != null)
+                {
+                    eventBlock.CollectionChanged -= value;
+                    if (eventBlock.events == 0) eventBlock = null;
+                }
+            }
+        }
+        /// <summary>
+        /// Fire the CollectionChanged event
+        /// </summary>
+        protected virtual void raiseCollectionChanged()
+        { if (eventBlock != null) eventBlock.raiseCollectionChanged(this); }
+
+        /// <summary>
+        /// The clear event. Will be raised for every Clear operation on the collection.
+        /// </summary>
+        public virtual event CollectionClearedHandler<T> CollectionCleared
+        {
+            add { checkWillListen(EventTypeEnum.Cleared); (eventBlock ?? (eventBlock = new EventBlock<T>())).CollectionCleared += value; }
+            remove
+            {
+                checkWillListen(EventTypeEnum.Cleared);
+                if (eventBlock != null)
+                {
+                    eventBlock.CollectionCleared -= value;
+                    if (eventBlock.events == 0) eventBlock = null;
+                }
+            }
+        }
+        /// <summary>
+        /// Fire the CollectionCleared event
+        /// </summary>
+        protected virtual void raiseCollectionCleared(bool full, int count)
+        { if (eventBlock != null) eventBlock.raiseCollectionCleared(this, full, count); }
+
+        /// <summary>
+        /// Fire the CollectionCleared event
+        /// </summary>
+        protected virtual void raiseCollectionCleared(bool full, int count, int? offset)
+        { if (eventBlock != null) eventBlock.raiseCollectionCleared(this, full, count, offset); }
+
+        /// <summary>
+        /// The item added  event. Will be raised for every individual addition to the collection.
+        /// </summary>
+        public virtual event ItemsAddedHandler<T> ItemsAdded
+        {
+            add { checkWillListen(EventTypeEnum.Added); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemsAdded += value; }
+            remove
+            {
+                checkWillListen(EventTypeEnum.Added);
+                if (eventBlock != null)
+                {
+                    eventBlock.ItemsAdded -= value;
+                    if (eventBlock.events == 0) eventBlock = null;
+                }
+            }
+        }
+        /// <summary>
+        /// Fire the ItemsAdded event
+        /// </summary>
+        /// <param name="item">The item that was added</param>
+        /// <param name="count"></param>
+        protected virtual void raiseItemsAdded(T item, int count)
+        { if (eventBlock != null) eventBlock.raiseItemsAdded(this, item, count); }
+
+        /// <summary>
+        /// The item removed event. Will be raised for every individual removal from the collection.
+        /// </summary>
+        public virtual event ItemsRemovedHandler<T> ItemsRemoved
+        {
+            add { checkWillListen(EventTypeEnum.Removed); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemsRemoved += value; }
+            remove
+            {
+                checkWillListen(EventTypeEnum.Removed);
+                if (eventBlock != null)
+                {
+                    eventBlock.ItemsRemoved -= value;
+                    if (eventBlock.events == 0) eventBlock = null;
+                }
+            }
+        }
+        /// <summary>
+        /// Fire the ItemsRemoved event
+        /// </summary>
+        /// <param name="item">The item that was removed</param>
+        /// <param name="count"></param>
+        protected virtual void raiseItemsRemoved(T item, int count)
+        { if (eventBlock != null) eventBlock.raiseItemsRemoved(this, item, count); }
+
+        /// <summary>
+        /// The item added  event. Will be raised for every individual addition to the collection.
+        /// </summary>
+        public virtual event ItemInsertedHandler<T> ItemInserted
+        {
+            add { checkWillListen(EventTypeEnum.Inserted); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemInserted += value; }
+            remove
+            {
+                checkWillListen(EventTypeEnum.Inserted);
+                if (eventBlock != null)
+                {
+                    eventBlock.ItemInserted -= value;
+                    if (eventBlock.events == 0) eventBlock = null;
+                }
+            }
+        }
+        /// <summary>
+        /// Fire the ItemInserted event
+        /// </summary>
+        /// <param name="item">The item that was added</param>
+        /// <param name="index"></param>
+        protected virtual void raiseItemInserted(T item, int index)
+        { if (eventBlock != null) eventBlock.raiseItemInserted(this, item, index); }
+
+        /// <summary>
+        /// The item removed event. Will be raised for every individual removal from the collection.
+        /// </summary>
+        public virtual event ItemRemovedAtHandler<T> ItemRemovedAt
+        {
+            add { checkWillListen(EventTypeEnum.RemovedAt); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemRemovedAt += value; }
+            remove
+            {
+                checkWillListen(EventTypeEnum.RemovedAt);
+                if (eventBlock != null)
+                {
+                    eventBlock.ItemRemovedAt -= value;
+                    if (eventBlock.events == 0) eventBlock = null;
+                }
+            }
+        }
+        /// <summary> 
+        /// Fire the ItemRemovedAt event
+        /// </summary>
+        /// <param name="item">The item that was removed</param>
+        /// <param name="index"></param>
+        protected virtual void raiseItemRemovedAt(T item, int index)
+        { if (eventBlock != null) eventBlock.raiseItemRemovedAt(this, item, index); }
+
+        #region Event support for IList
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="index"></param>
+        /// <param name="value"></param>
+        /// <param name="item"></param>
+        protected virtual void raiseForSetThis(int index, T value, T item)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(item, 1);
+                raiseItemRemovedAt(item, index);
+                raiseItemsAdded(value, 1);
+                raiseItemInserted(value, index);
+                raiseCollectionChanged();
+            }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="i"></param>
+        /// <param name="item"></param>
+        protected virtual void raiseForInsert(int i, T item)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemInserted(item, i);
+                raiseItemsAdded(item, 1);
+                raiseCollectionChanged();
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        protected void raiseForRemove(T item)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(item, 1);
+                raiseCollectionChanged();
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="count"></param>
+        protected void raiseForRemove(T item, int count)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(item, count);
+                raiseCollectionChanged();
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="index"></param>
+        /// <param name="item"></param>
+        protected void raiseForRemoveAt(int index, T item)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemRemovedAt(item, index);
+                raiseItemsRemoved(item, 1);
+                raiseCollectionChanged();
+            }
+        }
+
+        #endregion
+
+        #region Event  Support for ICollection
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="newitem"></param>
+        /// <param name="olditem"></param>
+        protected virtual void raiseForUpdate(T newitem, T olditem)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(olditem, 1);
+                raiseItemsAdded(newitem, 1);
+                raiseCollectionChanged();
+            }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="newitem"></param>
+        /// <param name="olditem"></param>
+        /// <param name="count"></param>
+        protected virtual void raiseForUpdate(T newitem, T olditem, int count)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemsRemoved(olditem, count);
+                raiseItemsAdded(newitem, count);
+                raiseCollectionChanged();
+            }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        protected virtual void raiseForAdd(T item)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseItemsAdded(item, 1);
+                raiseCollectionChanged();
+            }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="wasRemoved"></param>
+        protected virtual void raiseForRemoveAll(ICollectionValue<T> wasRemoved)
+        {
+            if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+                foreach (T item in wasRemoved)
+                    raiseItemsRemoved(item, 1);
+            if (wasRemoved != null && wasRemoved.Count > 0)
+                raiseCollectionChanged();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        [Serializable]
+        protected class RaiseForRemoveAllHandler
+        {
+            CollectionValueBase<T> collection;
+            CircularQueue<T> wasRemoved;
+            bool wasChanged = false;
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="collection"></param>
+            public RaiseForRemoveAllHandler(CollectionValueBase<T> collection)
+            {
+                this.collection = collection;
+                mustFireRemoved = (collection.ActiveEvents & EventTypeEnum.Removed) != 0;
+                MustFire = (collection.ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;
+            }
+
+            bool mustFireRemoved;
+            /// <summary>
+            /// 
+            /// </summary>
+            public readonly bool MustFire;
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <param name="item"></param>
+            public void Remove(T item)
+            {
+                if (mustFireRemoved)
+                {
+                    if (wasRemoved == null)
+                        wasRemoved = new CircularQueue<T>();
+                    wasRemoved.Enqueue(item);
+                }
+                if (!wasChanged)
+                    wasChanged = true;
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            public void Raise()
+            {
+                if (wasRemoved != null)
+                    foreach (T item in wasRemoved)
+                        collection.raiseItemsRemoved(item, 1);
+                if (wasChanged)
+                    collection.raiseCollectionChanged();
+            }
+        }
+        #endregion
+
+        #endregion
+
+        internal MemoryType MemoryType { get; set; }
+
+        /// <summary>
+        /// Check if collection is empty.
+        /// </summary>
+        /// <value>True if empty</value>
+        public abstract bool IsEmpty { get; }
+
+        /// <summary>
+        /// The number of items in this collection.
+        /// </summary>
+        /// <value></value>
+        public abstract int Count { get; }
+
+        /// <summary>
+        /// The value is symbolic indicating the type of asymptotic complexity
+        /// in terms of the size of this collection (worst-case or amortized as
+        /// relevant).
+        /// </summary>
+        /// <value>A characterization of the speed of the 
+        /// <code>Count</code> property in this collection.</value>
+        public abstract Speed CountSpeed { get; }
+
+        /// <summary>
+        /// Copy the items of this collection to part of an array.
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException"> if <code>index</code> 
+        /// is not a valid index
+        /// into the array (i.e. negative or greater than the size of the array)
+        /// or the array does not have room for the items.</exception>
+        /// <param name="array">The array to copy to.</param>
+        /// <param name="index">The starting index.</param>
+        public virtual void CopyTo(T[] array, int index)
+        {
+            if (index < 0 || index + Count > array.Length)
+                throw new ArgumentOutOfRangeException();
+
+            foreach (T item in this) array[index++] = item;
+        }
+
+        /// <summary>
+        /// Create an array with the items of this collection (in the same order as an
+        /// enumerator would output them).
+        /// </summary>
+        /// <returns>The array</returns>
+        public virtual T[] ToArray()
+        {
+            T[] res = new T[Count];
+            int i = 0;
+
+            foreach (T item in this) res[i++] = item;
+
+            return res;
+        }
+
+        /// <summary>
+        /// Apply an single argument action, <see cref="T:Action`1"/> to this enumerable
+        /// </summary>
+        /// <param name="action">The action delegate</param>
+        public virtual void Apply(Action<T> action)
+        {
+            foreach (T item in this)
+                action(item);
+        }
+
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R = bool</code>) 
+        /// defining the predicate</param>
+        /// <returns>True if such an item exists</returns>
+        public virtual bool Exists(Func<T, bool> predicate)
+        {
+            foreach (T item in this)
+                if (predicate(item))
+                    return true;
+
+            return false;
+        }
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection and return the first one in enumeration order.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R == bool</code>) defining the predicate</param>
+        /// <param name="item"></param>
+        /// <returns>True is such an item exists</returns>
+        public virtual bool Find(Func<T, bool> predicate, out T item)
+        {
+            foreach (T jtem in this)
+                if (predicate(jtem))
+                {
+                    item = jtem;
+                    return true;
+                }
+            item = default(T);
+            return false;
+        }
+
+        /// <summary>
+        /// Check if all items in this collection satisfies a specific predicate.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R = bool</code>) 
+        /// defining the predicate</param>
+        /// <returns>True if all items satisfies the predicate</returns>
+        public virtual bool All(Func<T, bool> predicate)
+        {
+            foreach (T item in this)
+                if (!predicate(item))
+                    return false;
+
+            return true;
+        }
+
+        /// <summary>
+        /// Create an enumerable, enumerating the items of this collection that satisfies 
+        /// a certain condition.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R = bool</code>) 
+        /// defining the predicate</param>
+        /// <returns>The filtered enumerable</returns>
+        public virtual SCG.IEnumerable<T> Filter(Func<T, bool> predicate)
+        {
+            if (MemoryType == MemoryType.Strict) throw new Exception("This is not a memory safe function and cannot be used in MemoryType.Strict");
+
+            foreach (T item in this)
+                if (predicate(item))
+                    yield return item;
+        }
+
+        /// <summary>
+        /// Choose some item of this collection. 
+        /// </summary>
+        /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+        /// <returns></returns>
+        public abstract T Choose();
+
+
+        #region IShowable Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="stringbuilder"></param>
+        /// <param name="rest"></param>
+        /// <param name="formatProvider"></param>
+        /// <returns></returns>
+        public virtual bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+        {
+            return Showing.ShowCollectionValue<T>(this, stringbuilder, ref rest, formatProvider);
+        }
+        #endregion
+
+        #region IFormattable Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="format"></param>
+        /// <param name="formatProvider"></param>
+        /// <returns></returns>
+        public virtual string ToString(string format, IFormatProvider formatProvider)
+        {
+            return Showing.ShowString(this, format, formatProvider);
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString()
+        {
+            return ToString(null, null);
+        }
+    }
+
+
+    /// <summary>
+    /// A base class for implementing a dictionary based on a set collection implementation.
+    /// <i>See the source code for <see cref="T:C5.HashDictionary`2"/> for an example</i>
+    /// 
+    /// </summary>
+    [Serializable]
+    public abstract class DictionaryBase<K, V> : CollectionValueBase<KeyValuePair<K, V>>, IDictionary<K, V>
+    {
+        /// <summary>
+        /// The set collection of entries underlying this dictionary implementation
+        /// </summary>
+        protected ICollection<KeyValuePair<K, V>> pairs;
+
+        SCG.IEqualityComparer<K> keyequalityComparer;
+
+        private readonly KeysCollection _keyCollection;
+        private readonly ValuesCollection _valueCollection;
+
+        #region Events
+
+        ProxyEventBlock<KeyValuePair<K, V>> eventBlock;
+
+        /// <summary>
+        /// The change event. Will be raised for every change operation on the collection.
+        /// </summary>
+        public override event CollectionChangedHandler<KeyValuePair<K, V>> CollectionChanged
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).CollectionChanged += value; }
+            remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
+        }
+
+        /// <summary>
+        /// The change event. Will be raised for every change operation on the collection.
+        /// </summary>
+        public override event CollectionClearedHandler<KeyValuePair<K, V>> CollectionCleared
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).CollectionCleared += value; }
+            remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
+        }
+
+        /// <summary>
+        /// The item added  event. Will be raised for every individual addition to the collection.
+        /// </summary>
+        public override event ItemsAddedHandler<KeyValuePair<K, V>> ItemsAdded
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).ItemsAdded += value; }
+            remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
+        }
+
+        /// <summary>
+        /// The item added  event. Will be raised for every individual removal from the collection.
+        /// </summary>
+        public override event ItemsRemovedHandler<KeyValuePair<K, V>> ItemsRemoved
+        {
+            add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).ItemsRemoved += value; }
+            remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public override EventTypeEnum ListenableEvents
+        {
+            get
+            {
+                return EventTypeEnum.Basic;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public override EventTypeEnum ActiveEvents
+        {
+            get
+            {
+                return pairs.ActiveEvents;
+            }
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="keyequalityComparer"></param>
+        /// <param name = "memoryType"></param>
+        protected DictionaryBase(SCG.IEqualityComparer<K> keyequalityComparer, MemoryType memoryType)
+        {
+            if (keyequalityComparer == null)
+                throw new NullReferenceException("Key equality comparer cannot be null");
+            this.keyequalityComparer = keyequalityComparer;
+            MemoryType = memoryType;
+
+            _keyCollection = new KeysCollection(pairs, memoryType);
+            _valueCollection = new ValuesCollection(pairs, memoryType);
+        }
+
+        #region IDictionary<K,V> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual SCG.IEqualityComparer<K> EqualityComparer { get { return keyequalityComparer; } }
+
+
+        /// <summary>
+        /// Add a new (key, value) pair (a mapping) to the dictionary.
+        /// </summary>
+        /// <exception cref="DuplicateNotAllowedException"> if there already is an entry with the same key. </exception>
+        /// <param name="key">Key to add</param>
+        /// <param name="value">Value to add</param>
+        public virtual void Add(K key, V value)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+            if (!pairs.Add(p))
+                throw new DuplicateNotAllowedException("Key being added: '" + key + "'");
+        }
+
+        /// <summary>
+        /// Add the entries from a collection of <see cref="T:C5.KeyValuePair`2"/> pairs to this dictionary.
+        /// <para><b>TODO: add restrictions L:K and W:V when the .Net SDK allows it </b></para>
+        /// </summary>
+        /// <exception cref="DuplicateNotAllowedException"> 
+        /// If the input contains duplicate keys or a key already present in this dictionary.</exception>
+        /// <param name="entries"></param>
+        public virtual void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> entries)
+            where L : K
+            where W : V
+        {
+            foreach (KeyValuePair<L, W> pair in entries)
+            {
+                KeyValuePair<K, V> p = new KeyValuePair<K, V>(pair.Key, pair.Value);
+                if (!pairs.Add(p))
+                    throw new DuplicateNotAllowedException("Key being added: '" + pair.Key + "'");
+            }
+        }
+
+        /// <summary>
+        /// Remove an entry with a given key from the dictionary
+        /// </summary>
+        /// <param name="key">The key of the entry to remove</param>
+        /// <returns>True if an entry was found (and removed)</returns>
+        public virtual bool Remove(K key)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+            return pairs.Remove(p);
+        }
+
+
+        /// <summary>
+        /// Remove an entry with a given key from the dictionary and report its value.
+        /// </summary>
+        /// <param name="key">The key of the entry to remove</param>
+        /// <param name="value">On exit, the value of the removed entry</param>
+        /// <returns>True if an entry was found (and removed)</returns>
+        public virtual bool Remove(K key, out V value)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+            if (pairs.Remove(p, out p))
+            {
+                value = p.Value;
+                return true;
+            }
+            else
+            {
+                value = default(V);
+                return false;
+            }
+        }
+
+
+        /// <summary>
+        /// Remove all entries from the dictionary
+        /// </summary>
+        public virtual void Clear() { pairs.Clear(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual Speed ContainsSpeed { get { return pairs.ContainsSpeed; } }
+
+        /// <summary>
+        /// Check if there is an entry with a specified key
+        /// </summary>
+        /// <param name="key">The key to look for</param>
+        /// <returns>True if key was found</returns>
+        public virtual bool Contains(K key)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+            return pairs.Contains(p);
+        }
+
+        [Serializable]
+        class LiftedEnumerable<H> : SCG.IEnumerable<KeyValuePair<K, V>> where H : K
+        {
+            SCG.IEnumerable<H> keys;
+            public LiftedEnumerable(SCG.IEnumerable<H> keys) { this.keys = keys; }
+            public SCG.IEnumerator<KeyValuePair<K, V>> GetEnumerator() { foreach (H key in keys) yield return new KeyValuePair<K, V>(key); }
+
+            #region IEnumerable Members
+
+            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+            {
+                throw new NotImplementedException();
+            }
+
+            #endregion
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="keys"></param>
+        /// <returns></returns>
+        public virtual bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K
+        {
+            if (MemoryType == MemoryType.Strict)
+                throw new Exception("The use of ContainsAll generates garbage as it still uses a non-memory safe enumerator");
+            return pairs.ContainsAll(new LiftedEnumerable<H>(keys));
+        }
+
+        /// <summary>
+        /// Check if there is an entry with a specified key and report the corresponding
+        /// value if found. This can be seen as a safe form of "val = this[key]".
+        /// </summary>
+        /// <param name="key">The key to look for</param>
+        /// <param name="value">On exit, the value of the entry</param>
+        /// <returns>True if key was found</returns>
+        public virtual bool Find(ref K key, out V value)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+            if (pairs.Find(ref p))
+            {
+                key = p.Key;
+                value = p.Value;
+                return true;
+            }
+            else
+            {
+                value = default(V);
+                return false;
+            }
+        }
+
+
+        /// <summary>
+        /// Look for a specific key in the dictionary and if found replace the value with a new one.
+        /// This can be seen as a non-adding version of "this[key] = val".
+        /// </summary>
+        /// <param name="key">The key to look for</param>
+        /// <param name="value">The new value</param>
+        /// <returns>True if key was found</returns>
+        public virtual bool Update(K key, V value)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+            return pairs.Update(p);
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="key"></param>
+        /// <param name="value"></param>
+        /// <param name="oldvalue"></param>
+        /// <returns></returns>
+        public virtual bool Update(K key, V value, out V oldvalue)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+            bool retval = pairs.Update(p, out p);
+            oldvalue = p.Value;
+            return retval;
+        }
+
+
+        /// <summary>
+        /// Look for a specific key in the dictionary. If found, report the corresponding value,
+        /// else add an entry with the key and the supplied value.
+        /// </summary>
+        /// <param name="key">On entry the key to look for</param>
+        /// <param name="value">On entry the value to add if the key is not found.
+        /// On exit the value found if any.</param>
+        /// <returns>True if key was found</returns>
+        public virtual bool FindOrAdd(K key, ref V value)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+            if (!pairs.FindOrAdd(ref p))
+                return false;
+            else
+            {
+                value = p.Value;
+                //key = p.key;
+                return true;
+            }
+        }
+
+
+        /// <summary>
+        /// Update value in dictionary corresponding to key if found, else add new entry.
+        /// More general than "this[key] = val;" by reporting if key was found.
+        /// </summary>
+        /// <param name="key">The key to look for</param>
+        /// <param name="value">The value to add or replace with.</param>
+        /// <returns>True if entry was updated.</returns>
+        public virtual bool UpdateOrAdd(K key, V value)
+        {
+            return pairs.UpdateOrAdd(new KeyValuePair<K, V>(key, value));
+        }
+
+
+        /// <summary>
+        /// Update value in dictionary corresponding to key if found, else add new entry.
+        /// More general than "this[key] = val;" by reporting if key was found and the old value if any.
+        /// </summary>
+        /// <param name="key"></param>
+        /// <param name="value"></param>
+        /// <param name="oldvalue"></param>
+        /// <returns></returns>
+        public virtual bool UpdateOrAdd(K key, V value, out V oldvalue)
+        {
+            KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+            bool retval = pairs.UpdateOrAdd(p, out p);
+            oldvalue = p.Value;
+            return retval;
+        }
+
+
+
+        #region Keys,Values support classes
+        [Serializable]
+        internal class ValuesCollection : CollectionValueBase<V>, ICollectionValue<V>
+        {
+            private ICollection<KeyValuePair<K, V>> _pairs;
+            private readonly ValueEnumerator _valueEnumerator;
+
+
+            internal ValuesCollection(ICollection<KeyValuePair<K, V>> keyValuePairs, MemoryType memoryType)
+            {
+                _pairs = keyValuePairs;
+                _valueEnumerator = new ValueEnumerator(keyValuePairs, memoryType);
+            }
+
+
+            #region Private Enumerator
+
+            [Serializable]
+            private class ValueEnumerator : MemorySafeEnumerator<V>
+            {
+                private ICollection<KeyValuePair<K, V>> _keyValuePairs;
+
+                private SCG.IEnumerator<KeyValuePair<K, V>> _keyValuePairEnumerator;
+
+                public ValueEnumerator(ICollection<KeyValuePair<K, V>> keyValuePairs, MemoryType memoryType)
+                    : base(memoryType)
+                {
+                    _keyValuePairs = keyValuePairs;
+                }
+
+                internal void UpdateReference(ICollection<KeyValuePair<K, V>> keyValuePairs)
+                {
+                    _keyValuePairs = keyValuePairs;
+                    Current = default(V);
+                }
+
+                public override bool MoveNext()
+                {
+                    ICollection<KeyValuePair<K, V>> list = _keyValuePairs;
+
+                    if (_keyValuePairEnumerator == null)
+                        _keyValuePairEnumerator = list.GetEnumerator();
+
+                    if (_keyValuePairEnumerator.MoveNext())
+                    {
+                        var curr = _keyValuePairEnumerator.Current;
+                        Current = curr.Value;
+                        return true;
+                    }
+
+                    _keyValuePairEnumerator.Dispose();
+                    Current = default(V);
+                    return false;
+                }
+
+                public override void Reset()
+                {
+                    Current = default(V);
+                }
+                protected override MemorySafeEnumerator<V> Clone()
+                {
+                    var enumerator = new ValueEnumerator(_keyValuePairs, MemoryType)
+                    {
+                        Current = default(V)
+                    };
+                    return enumerator;
+                }
+            }
+
+            #endregion
+
+
+            public override V Choose()
+            {
+                return _pairs.Choose().Value;
+            }
+
+            public override SCG.IEnumerator<V> GetEnumerator()
+            {
+                //Updatecheck is performed by the pairs enumerator
+                var enumerator = (ValueEnumerator)_valueEnumerator.GetEnumerator();
+                enumerator.UpdateReference(_pairs);
+                return enumerator;
+            }
+
+            public override bool IsEmpty { get { return _pairs.IsEmpty; } }
+
+            public override int Count { get { return _pairs.Count; } }
+
+            public override Speed CountSpeed { get { return Speed.Constant; } }
+
+            public void Update(ICollection<KeyValuePair<K, V>> keyValuePairs)
+            {
+                _pairs = keyValuePairs;
+            }
+        }
+
+        [Serializable]
+        internal class KeysCollection : CollectionValueBase<K>, ICollectionValue<K>
+        {
+            ICollection<KeyValuePair<K, V>> _pairs;
+
+            private readonly KeyEnumerator _keyEnumerator;
+
+            #region Private Enumerator
+
+            [Serializable]
+            private class KeyEnumerator : MemorySafeEnumerator<K>
+            {
+                private ICollection<KeyValuePair<K, V>> _internalList;
+
+                private SCG.IEnumerator<KeyValuePair<K, V>> _keyValuePairEnumerator;
+
+                public KeyEnumerator(ICollection<KeyValuePair<K, V>> list, MemoryType memoryType)
+                    : base(memoryType)
+                {
+                    _internalList = list;
+                }
+
+                internal void UpdateReference(ICollection<KeyValuePair<K, V>> list)
+                {
+                    _internalList = list;
+                    Current = default(K);
+                }
+
+
+                public override bool MoveNext()
+                {
+                    ICollection<KeyValuePair<K, V>> list = _internalList;
+
+                    if (_keyValuePairEnumerator == null)
+                        _keyValuePairEnumerator = list.GetEnumerator();
+
+                    if (_keyValuePairEnumerator.MoveNext())
+                    {
+                        Current = _keyValuePairEnumerator.Current.Key;
+                        return true;
+                    }
+
+                    _keyValuePairEnumerator.Dispose();
+
+                    Current = default(K);
+                    return false;
+                }
+
+                public override void Reset()
+                {
+                    Current = default(K);
+                }
+
+                protected override MemorySafeEnumerator<K> Clone()
+                {
+                    var enumerator = new KeyEnumerator(_internalList, MemoryType)
+                    {
+                        Current = default(K)
+                    };
+                    return enumerator;
+                }
+            }
+
+            #endregion
+
+            internal KeysCollection(ICollection<KeyValuePair<K, V>> pairs, MemoryType memoryType)
+            {
+                _pairs = pairs;
+
+                _keyEnumerator = new KeyEnumerator(pairs, memoryType);
+            }
+
+            public void Update(ICollection<KeyValuePair<K, V>> pairs)
+            {
+                _pairs = pairs;
+            }
+
+            public override K Choose()
+            {
+                return _pairs.Choose().Key;
+            }
+
+            public override SCG.IEnumerator<K> GetEnumerator()
+            {
+                var enumerator = (KeyEnumerator)_keyEnumerator.GetEnumerator();
+                enumerator.UpdateReference(_pairs);
+                return enumerator;
+            }
+
+            public override bool IsEmpty { get { return _pairs.IsEmpty; } }
+
+            public override int Count { get { return _pairs.Count; } }
+
+            public override Speed CountSpeed { get { return _pairs.CountSpeed; } }
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>A collection containing all the keys of the dictionary</value>
+        public virtual ICollectionValue<K> Keys
+        {
+            get
+            {
+                _keyCollection.Update(pairs);
+                return _keyCollection;
+
+            }
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>A collection containing all the values of the dictionary</value>
+        public virtual ICollectionValue<V> Values
+        {
+            get
+            {
+                _valueCollection.Update(pairs);
+                return _valueCollection;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public virtual Func<K, V> Func { get { return delegate (K k) { return this[k]; }; } }
+
+        /// <summary>
+        /// Indexer by key for dictionary. 
+        /// <para>The get method will throw an exception if no entry is found. </para>
+        /// <para>The set method behaves like <see cref="M:C5.DictionaryBase`2.UpdateOrAdd(`0,`1)"/>.</para>
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> On get if no entry is found. </exception>
+        /// <value>The value corresponding to the key</value>
+        public virtual V this[K key]
+        {
+            get
+            {
+                KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+                if (pairs.Find(ref p))
+                    return p.Value;
+                else
+                    throw new NoSuchItemException("Key '" + key.ToString() + "' not present in Dictionary");
+            }
+            set
+            { pairs.UpdateOrAdd(new KeyValuePair<K, V>(key, value)); }
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>True if dictionary is read  only</value>
+        public virtual bool IsReadOnly { get { return pairs.IsReadOnly; } }
+
+
+        /// <summary>
+        /// Check the integrity of the internal data structures of this dictionary.
+        /// </summary>
+        /// <returns>True if check does not fail.</returns>
+        public virtual bool Check() { return pairs.Check(); }
+
+        #endregion
+
+        #region ICollectionValue<KeyValuePair<K,V>> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>True if this collection is empty.</value>
+        public override bool IsEmpty { get { return pairs.IsEmpty; } }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The number of entries in the dictionary</value>
+        public override int Count { get { return pairs.Count; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The number of entries in the dictionary</value>
+        public override Speed CountSpeed { get { return pairs.CountSpeed; } }
+
+        /// <summary>
+        /// Choose some entry in this Dictionary. 
+        /// </summary>
+        /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+        /// <returns></returns>
+        public override KeyValuePair<K, V> Choose() { return pairs.Choose(); }
+
+        /// <summary>
+        /// Create an enumerator for the collection of entries of the dictionary
+        /// </summary>
+        /// <returns>The enumerator</returns>
+        public override SCG.IEnumerator<KeyValuePair<K, V>> GetEnumerator()
+        {
+            return pairs.GetEnumerator();
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="stringbuilder"></param>
+        /// <param name="rest"></param>
+        /// <param name="formatProvider"></param>
+        /// <returns></returns>
+        public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+        {
+            return Showing.ShowDictionary<K, V>(this, stringbuilder, ref rest, formatProvider);
+        }
+    }
+
+
+    /// <summary>
+    /// A base class for implementing a sorted dictionary based on a sorted set collection implementation.
+    /// <i>See the source code for <see cref="T:C5.TreeDictionary`2"/> for an example</i>
+    /// 
+    /// </summary>
+    [Serializable]
+    public abstract class SortedDictionaryBase<K, V> : DictionaryBase<K, V>, ISortedDictionary<K, V>
+    {
+        #region Fields
+
+        /// <summary>
+        /// 
+        /// </summary>
+        protected ISorted<KeyValuePair<K, V>> sortedpairs;
+        SCG.IComparer<K> keycomparer;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="keycomparer"></param>
+        /// <param name="keyequalityComparer"></param>
+        /// <param name="memoryType">The memory type of the enumerator used to iterate the collection.</param>
+        protected SortedDictionaryBase(SCG.IComparer<K> keycomparer, SCG.IEqualityComparer<K> keyequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(keyequalityComparer, memoryType)
+        {
+            this.keycomparer = keycomparer;
+            MemoryType = memoryType;
+        }
+
+        #endregion
+
+        #region ISortedDictionary<K,V> Members
+
+        /// <summary>
+        /// The key comparer used by this dictionary.
+        /// </summary>
+        /// <value></value>
+        public SCG.IComparer<K> Comparer { get { return keycomparer; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        /// I should add something to return the same instance
+        public new ISorted<K> Keys { get { return new SortedKeysCollection(this, sortedpairs, keycomparer, EqualityComparer, MemoryType); } }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// predecessor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The predecessor, if any</param>
+        /// <returns>True if key has a predecessor</returns>
+        public bool TryPredecessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sortedpairs.TryPredecessor(new KeyValuePair<K, V>(key), out res);
+        }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// successor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The successor, if any</param>
+        /// <returns>True if the key has a successor</returns>
+        public bool TrySuccessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sortedpairs.TrySuccessor(new KeyValuePair<K, V>(key), out res);
+        }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// weak predecessor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The predecessor, if any</param>
+        /// <returns>True if key has a weak predecessor</returns>
+        public bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sortedpairs.TryWeakPredecessor(new KeyValuePair<K, V>(key), out res);
+        }
+
+        /// <summary>
+        /// Find the entry in the dictionary whose key is the
+        /// weak successor of the specified key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="res">The weak successor, if any</param>
+        /// <returns>True if the key has a weak successor</returns>
+        public bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res)
+        {
+            return sortedpairs.TryWeakSuccessor(new KeyValuePair<K, V>(key), out res);
+        }
+
+        /// <summary>
+        /// Get the entry in the dictionary whose key is the
+        /// predecessor of the specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"></exception>
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> Predecessor(K key)
+        {
+            return sortedpairs.Predecessor(new KeyValuePair<K, V>(key));
+        }
+
+        /// <summary>
+        /// Get the entry in the dictionary whose key is the
+        /// successor of the specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"></exception>
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> Successor(K key)
+        {
+            return sortedpairs.Successor(new KeyValuePair<K, V>(key));
+        }
+
+        /// <summary>
+        /// Get the entry in the dictionary whose key is the
+        /// weak predecessor of the specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"></exception>
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> WeakPredecessor(K key)
+        {
+            return sortedpairs.WeakPredecessor(new KeyValuePair<K, V>(key));
+        }
+
+        /// <summary>
+        /// Get the entry in the dictionary whose key is the
+        /// weak successor of the specified key.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"></exception>
+        /// <param name="key">The key</param>
+        /// <returns>The entry</returns>
+        public KeyValuePair<K, V> WeakSuccessor(K key)
+        {
+            return sortedpairs.WeakSuccessor(new KeyValuePair<K, V>(key));
+        }
+
+        #endregion
+
+        #region ISortedDictionary<K,V> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public KeyValuePair<K, V> FindMin()
+        {
+            return sortedpairs.FindMin();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public KeyValuePair<K, V> DeleteMin()
+        {
+            return sortedpairs.DeleteMin();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public KeyValuePair<K, V> FindMax()
+        {
+            return sortedpairs.FindMax();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public KeyValuePair<K, V> DeleteMax()
+        {
+            return sortedpairs.DeleteMax();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="cutter"></param>
+        /// <param name="lowEntry"></param>
+        /// <param name="lowIsValid"></param>
+        /// <param name="highEntry"></param>
+        /// <param name="highIsValid"></param>
+        /// <returns></returns>
+        public bool Cut(IComparable<K> cutter, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
+        {
+            return sortedpairs.Cut(new KeyValuePairComparable(cutter), out lowEntry, out lowIsValid, out highEntry, out highIsValid);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
+        {
+            return sortedpairs.RangeFrom(new KeyValuePair<K, V>(bot));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="bot"></param>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
+        {
+            return sortedpairs.RangeFromTo(new KeyValuePair<K, V>(bot), new KeyValuePair<K, V>(top));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="top"></param>
+        /// <returns></returns>
+        public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
+        {
+            return sortedpairs.RangeTo(new KeyValuePair<K, V>(top));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
+        {
+            return sortedpairs.RangeAll();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="items"></param>
+        public void AddSorted(SCG.IEnumerable<KeyValuePair<K, V>> items)
+        {
+            sortedpairs.AddSorted(items);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="lowKey"></param>
+        public void RemoveRangeFrom(K lowKey)
+        {
+            sortedpairs.RemoveRangeFrom(new KeyValuePair<K, V>(lowKey));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="lowKey"></param>
+        /// <param name="highKey"></param>
+        public void RemoveRangeFromTo(K lowKey, K highKey)
+        {
+            sortedpairs.RemoveRangeFromTo(new KeyValuePair<K, V>(lowKey), new KeyValuePair<K, V>(highKey));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="highKey"></param>
+        public void RemoveRangeTo(K highKey)
+        {
+            sortedpairs.RemoveRangeTo(new KeyValuePair<K, V>(highKey));
+        }
+
+        #endregion
+        [Serializable]
+        class KeyValuePairComparable : IComparable<KeyValuePair<K, V>>
+        {
+            IComparable<K> cutter;
+
+            internal KeyValuePairComparable(IComparable<K> cutter) { this.cutter = cutter; }
+
+            public int CompareTo(KeyValuePair<K, V> other) { return cutter.CompareTo(other.Key); }
+
+            public bool Equals(KeyValuePair<K, V> other) { return cutter.Equals(other.Key); }
+        }
+
+        [Serializable]
+        class ProjectedDirectedEnumerable : MappedDirectedEnumerable<KeyValuePair<K, V>, K>
+        {
+            public ProjectedDirectedEnumerable(IDirectedEnumerable<KeyValuePair<K, V>> directedpairs) : base(directedpairs) { }
+
+            public override K Map(KeyValuePair<K, V> pair) { return pair.Key; }
+
+        }
+
+        [Serializable]
+        class ProjectedDirectedCollectionValue : MappedDirectedCollectionValue<KeyValuePair<K, V>, K>
+        {
+            public ProjectedDirectedCollectionValue(IDirectedCollectionValue<KeyValuePair<K, V>> directedpairs) : base(directedpairs) { }
+
+            public override K Map(KeyValuePair<K, V> pair) { return pair.Key; }
+
+        }
+
+        [Serializable]
+        sealed class SortedKeysCollection : SequencedBase<K>, ISorted<K>
+        {
+
+            #region Private Enumerator
+
+            [Serializable]
+            private class KeyEnumerator : MemorySafeEnumerator<K>
+            {
+                private ICollection<KeyValuePair<K, V>> _internalList;
+
+                private SCG.IEnumerator<KeyValuePair<K, V>> _internalEnumerator;
+
+
+
+                public KeyEnumerator(ICollection<KeyValuePair<K, V>> list, MemoryType memoryType)
+                    : base(memoryType)
+                {
+                    _internalList = list;
+                }
+
+                internal void UpdateReference(ICollection<KeyValuePair<K, V>> list)
+                {
+                    _internalList = list;
+                    Current = default(K);
+                }
+
+
+                public override void Dispose()
+                {
+                    _internalEnumerator.Dispose();
+                    _internalEnumerator = null;
+                }
+
+                public override bool MoveNext()
+                {
+                    ICollection<KeyValuePair<K, V>> list = _internalList;
+
+                    if (IteratorState == -1 || IteratorState == 0) // enumerator hasn't initialized yet or it has already run
+                        _internalEnumerator = list.GetEnumerator();
+
+                    IteratorState = 1;
+
+                    if (_internalEnumerator.MoveNext())
+                    {
+                        Current = _internalEnumerator.Current.Key;
+                        return true;
+                    }
+
+                    IteratorState = 0;
+                    return false;
+                }
+                public override void Reset()
+                {
+                    try
+                    {
+                        _internalEnumerator.Reset();
+                    }
+                    catch (Exception)
+                    {
+                        //swallow the exception
+                    }
+                    finally
+                    {
+                        Current = default(K);
+                    }
+                }
+
+
+                protected override MemorySafeEnumerator<K> Clone()
+                {
+                    var enumerator = new KeyEnumerator(_internalList, MemoryType)
+                    {
+                        Current = default(K)
+                    };
+                    return enumerator;
+                }
+            }
+
+            #endregion
+
+            private readonly KeyEnumerator _internalEnumerator;
+
+            ISortedDictionary<K, V> sorteddict;
+            //TODO: eliminate this. Only problem is the Find method because we lack method on dictionary that also
+            //      returns the actual key.
+            ISorted<KeyValuePair<K, V>> sortedpairs;
+            SCG.IComparer<K> comparer;
+
+            internal SortedKeysCollection(ISortedDictionary<K, V> sorteddict, ISorted<KeyValuePair<K, V>> sortedpairs, SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> itemequalityComparer, MemoryType memoryType)
+                : base(itemequalityComparer, memoryType)
+            {
+                this.sorteddict = sorteddict;
+                this.sortedpairs = sortedpairs;
+                this.comparer = comparer;
+
+                _internalEnumerator = new KeyEnumerator(sortedpairs, memoryType);
+            }
+
+            public override K Choose()
+            {
+                return sorteddict.Choose().Key;
+            }
+
+            public override SCG.IEnumerator<K> GetEnumerator()
+            {
+                _internalEnumerator.UpdateReference(sortedpairs);
+                return _internalEnumerator.GetEnumerator();
+                //                foreach (KeyValuePair<K, V> p in sorteddict)
+                //                    yield return p.Key;
+            }
+
+            public override bool IsEmpty { get { return sorteddict.IsEmpty; } }
+
+            public override int Count { get { return sorteddict.Count; } }
+
+            public override Speed CountSpeed { get { return sorteddict.CountSpeed; } }
+
+            #region ISorted<K> Members
+
+            public K FindMin() { return sorteddict.FindMin().Key; }
+
+            public K DeleteMin() { throw new ReadOnlyCollectionException(); }
+
+            public K FindMax() { return sorteddict.FindMax().Key; }
+
+            public K DeleteMax() { throw new ReadOnlyCollectionException(); }
+
+            public SCG.IComparer<K> Comparer { get { return comparer; } }
+
+            public bool TryPredecessor(K item, out K res)
+            {
+                KeyValuePair<K, V> pRes;
+                bool success = sorteddict.TryPredecessor(item, out pRes);
+                res = pRes.Key;
+                return success;
+            }
+
+            public bool TrySuccessor(K item, out K res)
+            {
+                KeyValuePair<K, V> pRes;
+                bool success = sorteddict.TrySuccessor(item, out pRes);
+                res = pRes.Key;
+                return success;
+            }
+
+            public bool TryWeakPredecessor(K item, out K res)
+            {
+                KeyValuePair<K, V> pRes;
+                bool success = sorteddict.TryWeakPredecessor(item, out pRes);
+                res = pRes.Key;
+                return success;
+            }
+
+            public bool TryWeakSuccessor(K item, out K res)
+            {
+                KeyValuePair<K, V> pRes;
+                bool success = sorteddict.TryWeakSuccessor(item, out pRes);
+                res = pRes.Key;
+                return success;
+            }
+
+            public K Predecessor(K item) { return sorteddict.Predecessor(item).Key; }
+
+            public K Successor(K item) { return sorteddict.Successor(item).Key; }
+
+            public K WeakPredecessor(K item) { return sorteddict.WeakPredecessor(item).Key; }
+
+            public K WeakSuccessor(K item) { return sorteddict.WeakSuccessor(item).Key; }
+
+            public bool Cut(IComparable<K> c, out K low, out bool lowIsValid, out K high, out bool highIsValid)
+            {
+                KeyValuePair<K, V> lowpair, highpair;
+                bool retval = sorteddict.Cut(c, out lowpair, out lowIsValid, out highpair, out highIsValid);
+                low = lowpair.Key;
+                high = highpair.Key;
+                return retval;
+            }
+
+            public IDirectedEnumerable<K> RangeFrom(K bot)
+            {
+                return new ProjectedDirectedEnumerable(sorteddict.RangeFrom(bot));
+            }
+
+            public IDirectedEnumerable<K> RangeFromTo(K bot, K top)
+            {
+                return new ProjectedDirectedEnumerable(sorteddict.RangeFromTo(bot, top));
+            }
+
+            public IDirectedEnumerable<K> RangeTo(K top)
+            {
+                return new ProjectedDirectedEnumerable(sorteddict.RangeTo(top));
+            }
+
+            public IDirectedCollectionValue<K> RangeAll()
+            {
+                return new ProjectedDirectedCollectionValue(sorteddict.RangeAll());
+            }
+
+            public void AddSorted(SCG.IEnumerable<K> items) { throw new ReadOnlyCollectionException(); }
+
+            public void RemoveRangeFrom(K low) { throw new ReadOnlyCollectionException(); }
+
+            public void RemoveRangeFromTo(K low, K hi) { throw new ReadOnlyCollectionException(); }
+
+            public void RemoveRangeTo(K hi) { throw new ReadOnlyCollectionException(); }
+            #endregion
+
+            #region ICollection<K> Members
+            public Speed ContainsSpeed { get { return sorteddict.ContainsSpeed; } }
+
+            public bool Contains(K key) { return sorteddict.Contains(key); ; }
+
+            public int ContainsCount(K item) { return sorteddict.Contains(item) ? 1 : 0; }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <returns></returns>
+            public ICollectionValue<K> UniqueItems()
+            {
+                return this;
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <returns></returns>
+            public ICollectionValue<KeyValuePair<K, int>> ItemMultiplicities()
+            {
+                return new MultiplicityOne<K>(this);
+            }
+
+
+            public bool ContainsAll(SCG.IEnumerable<K> items)
+            {
+                //TODO: optimize?
+                foreach (K item in items)
+                    if (!sorteddict.Contains(item))
+                        return false;
+                return true;
+            }
+
+            public bool Find(ref K item)
+            {
+                KeyValuePair<K, V> p = new KeyValuePair<K, V>(item);
+                bool retval = sortedpairs.Find(ref p);
+                item = p.Key;
+                return retval;
+            }
+
+            public bool FindOrAdd(ref K item) { throw new ReadOnlyCollectionException(); }
+
+            public bool Update(K item) { throw new ReadOnlyCollectionException(); }
+
+            public bool Update(K item, out K olditem) { throw new ReadOnlyCollectionException(); }
+
+            public bool UpdateOrAdd(K item) { throw new ReadOnlyCollectionException(); }
+
+            public bool UpdateOrAdd(K item, out K olditem) { throw new ReadOnlyCollectionException(); }
+
+            public bool Remove(K item) { throw new ReadOnlyCollectionException(); }
+
+            public bool Remove(K item, out K removeditem) { throw new ReadOnlyCollectionException(); }
+
+            public void RemoveAllCopies(K item) { throw new ReadOnlyCollectionException(); }
+
+            public void RemoveAll(SCG.IEnumerable<K> items) { throw new ReadOnlyCollectionException(); }
+
+            public void Clear() { throw new ReadOnlyCollectionException(); }
+
+            public void RetainAll(SCG.IEnumerable<K> items) { throw new ReadOnlyCollectionException(); }
+
+            #endregion
+
+            #region IExtensible<K> Members
+            public override bool IsReadOnly { get { return true; } }
+
+            public bool AllowsDuplicates { get { return false; } }
+
+            public bool DuplicatesByCounting { get { return true; } }
+
+            public bool Add(K item) { throw new ReadOnlyCollectionException(); }
+
+            void SCG.ICollection<K>.Add(K item) { throw new ReadOnlyCollectionException(); }
+
+            public void AddAll(System.Collections.Generic.IEnumerable<K> items) { throw new ReadOnlyCollectionException(); }
+
+            public bool Check() { return sorteddict.Check(); }
+
+            #endregion
+
+            #region IDirectedCollectionValue<K> Members
+
+            public override IDirectedCollectionValue<K> Backwards()
+            {
+                return RangeAll().Backwards();
+            }
+
+            #endregion
+
+            #region IDirectedEnumerable<K> Members
+
+            IDirectedEnumerable<K> IDirectedEnumerable<K>.Backwards() { return Backwards(); }
+            #endregion
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="stringbuilder"></param>
+        /// <param name="rest"></param>
+        /// <param name="formatProvider"></param>
+        /// <returns></returns>
+        public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+        {
+            return Showing.ShowDictionary<K, V>(this, stringbuilder, ref rest, formatProvider);
+        }
+
+    }
+
+    /// <summary>
+    /// Base class (abstract) for sequenced collection implementations.
+    /// </summary>
+    [Serializable]
+    public abstract class SequencedBase<T> : DirectedCollectionBase<T>, IDirectedCollectionValue<T>
+    {
+        #region Fields
+
+        int iSequencedHashCode, iSequencedHashCodeStamp = -1;
+
+        #endregion
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="itemequalityComparer"></param>
+        /// <param name = "memoryType">The type of memory for the enumerator used to iterate the collection</param>
+        protected SequencedBase(SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType) : base(itemequalityComparer, memoryType) { }
+
+        #region Util
+
+        //TODO: make random for release
+        const int HASHFACTOR = 31;
+
+        /// <summary>
+        /// Compute the unsequenced hash code of a collection
+        /// </summary>
+        /// <param name="items">The collection to compute hash code for</param>
+        /// <param name="itemequalityComparer">The item equalitySCG.Comparer</param>
+        /// <returns>The hash code</returns>
+        public static int ComputeHashCode(ISequenced<T> items, SCG.IEqualityComparer<T> itemequalityComparer)
+        {
+            //NOTE: It must be possible to devise a much stronger combined hashcode, 
+            //but unfortunately, it has to be universal. OR we could use a (strong)
+            //family and initialise its parameter randomly at load time of this class!
+            //(We would not want to have yet a flag to check for invalidation?!)
+            //NBNBNB: the current hashcode has the very bad property that items with hashcode 0
+            // is ignored.
+            int iIndexedHashCode = 0;
+
+            foreach (T item in items)
+                iIndexedHashCode = iIndexedHashCode * HASHFACTOR + itemequalityComparer.GetHashCode(item);
+
+            return iIndexedHashCode;
+        }
+
+
+        /// <summary>
+        /// Examine if tit and tat are equal as sequenced collections
+        /// using the specified item equalityComparer (assumed compatible with the two collections).
+        /// </summary>
+        /// <param name="collection1">The first collection</param>
+        /// <param name="collection2">The second collection</param>
+        /// <param name="itemequalityComparer">The item equalityComparer to use for comparison</param>
+        /// <returns>True if equal</returns>
+        public static bool StaticEquals(ISequenced<T> collection1, ISequenced<T> collection2, SCG.IEqualityComparer<T> itemequalityComparer)
+        {
+            if (ReferenceEquals(collection1, collection2))
+                return true;
+
+            if (collection1.Count != collection2.Count)
+                return false;
+
+            //This way we might run through both enumerations twice, but
+            //probably not (if the hash codes are good)
+            if (collection1.GetSequencedHashCode() != collection2.GetSequencedHashCode())
+                return false;
+
+            using (SCG.IEnumerator<T> dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator())
+            {
+                while (dit.MoveNext())
+                {
+                    dat.MoveNext();
+                    if (!itemequalityComparer.Equals(dit.Current, dat.Current))
+                        return false;
+                }
+            }
+
+            return true;
+        }
+
+
+        /// <summary>
+        /// Get the sequenced collection hash code of this collection: from the cached 
+        /// value if present and up to date, else (re)compute.
+        /// </summary>
+        /// <returns>The hash code</returns>
+        public virtual int GetSequencedHashCode()
+        {
+            if (iSequencedHashCodeStamp == stamp)
+                return iSequencedHashCode;
+
+            iSequencedHashCode = ComputeHashCode((ISequenced<T>)this, itemequalityComparer);
+            iSequencedHashCodeStamp = stamp;
+            return iSequencedHashCode;
+        }
+
+
+        /// <summary>
+        /// Check if the contents of that is equal to the contents of this
+        /// in the sequenced sense. Using the item equalityComparer of this collection.
+        /// </summary>
+        /// <param name="otherCollection">The collection to compare to.</param>
+        /// <returns>True if  equal</returns>
+        public virtual bool SequencedEquals(ISequenced<T> otherCollection)
+        {
+            return StaticEquals((ISequenced<T>)this, otherCollection, itemequalityComparer);
+        }
+
+
+        #endregion
+
+        /// <summary>
+        /// <code>Forwards</code> if same, else <code>Backwards</code>
+        /// </summary>
+        /// <value>The enumeration direction relative to the original collection.</value>
+        public override EnumerationDirection Direction { get { return EnumerationDirection.Forwards; } }
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection and return the index of the first one.
+        /// </summary>
+        /// <param name="predicate">A delegate defining the predicate</param>
+        /// <returns>the index, if found, a negative value else</returns>
+        public int FindIndex(Func<T, bool> predicate)
+        {
+            int index = 0;
+            foreach (T item in this)
+            {
+                if (predicate(item))
+                    return index;
+                index++;
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection and return the index of the last one.
+        /// </summary>
+        /// <param name="predicate">A delegate defining the predicate</param>
+        /// <returns>the index, if found, a negative value else</returns>
+        public int FindLastIndex(Func<T, bool> predicate)
+        {
+            int index = Count - 1;
+            foreach (T item in Backwards())
+            {
+                if (predicate(item))
+                    return index;
+                index--;
+            }
+            return -1;
+        }
+
+    }
+
+    /// <summary>
+    /// Base class (abstract) for ICollection implementations.
+    /// </summary>
+    [Serializable]
+    public abstract class CollectionBase<T> : CollectionValueBase<T>
+    {
+        #region Fields
+
+        /// <summary>
+        /// The underlying field of the ReadOnly property
+        /// </summary>
+        protected bool isReadOnlyBase = false;
+
+        /// <summary>
+        /// The current stamp value
+        /// </summary>
+        protected int stamp { get; set; }
+
+        /// <summary>
+        /// The number of items in the collection
+        /// </summary>
+        protected int size;
+
+        /// <summary>
+        /// The item equalityComparer of the collection
+        /// </summary>
+        protected readonly SCG.IEqualityComparer<T> itemequalityComparer;
+
+        int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1;
+
+        #endregion
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="itemequalityComparer"></param>
+        /// <param name = "memoryType">The type of memory for the enumerator used to iterate the collection</param>
+        protected CollectionBase(SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType)
+        {
+            if (itemequalityComparer == null)
+                throw new NullReferenceException("Item EqualityComparer cannot be null.");
+            this.itemequalityComparer = itemequalityComparer;
+
+            MemoryType = memoryType;
+        }
+
+        #region Util
+
+        /// <summary>
+        /// Utility method for range checking.
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative or
+        ///  if the range does not fit within collection size.</exception>
+        /// <param name="start">start of range</param>
+        /// <param name="count">size of range</param>
+        protected void checkRange(int start, int count)
+        {
+            if (start < 0 || count < 0 || start + count > size)
+                throw new ArgumentOutOfRangeException();
+        }
+
+
+        /// <summary>
+        /// Compute the unsequenced hash code of a collection
+        /// </summary>
+        /// <param name="items">The collection to compute hash code for</param>
+        /// <param name="itemequalityComparer">The item equalitySCG.Comparer</param>
+        /// <returns>The hash code</returns>
+        public static int ComputeHashCode(ICollectionValue<T> items, SCG.IEqualityComparer<T> itemequalityComparer)
+        {
+            int h = 0;
+
+            //But still heuristic: 
+            //Note: the three odd factors should really be random, 
+            //but there will be a problem with serialization/deserialization!
+            //Two products is too few
+            foreach (T item in items)
+            {
+                uint h1 = (uint)itemequalityComparer.GetHashCode(item);
+
+                h += (int)((h1 * 1529784657 + 1) ^ (h1 * 2912831877) ^ (h1 * 1118771817 + 2));
+            }
+
+            return h;
+            /*
+                  The pairs (-1657792980, -1570288808) and (1862883298, -272461342) gives the same
+                  unsequenced hashcode with this hashfunction. The pair was found with code like
+
+                  HashDictionary<int, int[]> set = new HashDictionary<int, int[]>();
+                  Random rnd = new C5Random(12345);
+                  while (true)
+                  {
+                      int[] a = new int[2];
+                      a[0] = rnd.Next(); a[1] = rnd.Next();
+                      int h = unsequencedhashcode(a);
+                      int[] b = a;
+                      if (set.FindOrAdd(h, ref b))
+                      {
+                          Logger.Log(string.Format("Code {5}, Pair ({1},{2}) number {0} matched other pair ({3},{4})", set.Count, a[0], a[1], b[0], b[1], h));
+                      }
+                  }
+                  */
+
+        }
+
+        static Type isortedtype = typeof(ISorted<T>);
+
+        /// <summary>
+        /// Examine if collection1 and collection2 are equal as unsequenced collections
+        /// using the specified item equalityComparer (assumed compatible with the two collections).
+        /// </summary>
+        /// <param name="collection1">The first collection</param>
+        /// <param name="collection2">The second collection</param>
+        /// <param name="itemequalityComparer">The item equalityComparer to use for comparison</param>
+        /// <returns>True if equal</returns>
+        public static bool StaticEquals(ICollection<T> collection1, ICollection<T> collection2, SCG.IEqualityComparer<T> itemequalityComparer)
+        {
+            if (ReferenceEquals(collection1, collection2))
+                return true;
+
+            // bug20070227:
+            if (collection1 == null || collection2 == null)
+                return false;
+
+            if (collection1.Count != collection2.Count)
+                return false;
+
+            //This way we might run through both enumerations twice, but
+            //probably not (if the hash codes are good)
+            //TODO: check equal equalityComparers, at least here!
+            if (collection1.GetUnsequencedHashCode() != collection2.GetUnsequencedHashCode())
+                return false;
+
+            //TODO: move this to the sorted implementation classes? 
+            //Really depends on speed of InstanceOfType: we could save a cast
+            {
+                ISorted<T> stit, stat;
+                if ((stit = collection1 as ISorted<T>) != null && (stat = collection2 as ISorted<T>) != null && stit.Comparer == stat.Comparer)
+                {
+                    using (SCG.IEnumerator<T> dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator())
+                    {
+                        while (dit.MoveNext())
+                        {
+                            dat.MoveNext();
+                            if (!itemequalityComparer.Equals(dit.Current, dat.Current))
+                                return false;
+                        }
+                        return true;
+                    }
+                }
+            }
+
+            if (!collection1.AllowsDuplicates && (collection2.AllowsDuplicates || collection2.ContainsSpeed >= collection1.ContainsSpeed))
+            {
+                foreach (T x in collection1) if (!collection2.Contains(x)) return false;
+            }
+            else if (!collection2.AllowsDuplicates)
+            {
+                foreach (T x in collection2) if (!collection1.Contains(x)) return false;
+            }
+            // Now tit.AllowsDuplicates && tat.AllowsDuplicates
+            else if (collection1.DuplicatesByCounting && collection2.DuplicatesByCounting)
+            {
+                foreach (T item in collection2) if (collection1.ContainsCount(item) != collection2.ContainsCount(item)) return false;
+            }
+            else
+            {
+                // To avoid an O(n^2) algorithm, we make an aux hashtable to hold the count of items
+                // bug20101103: HashDictionary<T, int> dict = new HashDictionary<T, int>();
+                HashDictionary<T, int> dict = new HashDictionary<T, int>(itemequalityComparer);
+                foreach (T item in collection2)
+                {
+                    int count = 1;
+                    if (dict.FindOrAdd(item, ref count))
+                        dict[item] = count + 1;
+                }
+                foreach (T item in collection1)
+                {
+                    var i = item;
+                    int count;
+                    if (dict.Find(ref i, out count) && count > 0)
+                        dict[item] = count - 1;
+                    else
+                        return false;
+                }
+                return true;
+            }
+
+            return true;
+        }
+
+
+        /// <summary>
+        /// Get the unsequenced collection hash code of this collection: from the cached 
+        /// value if present and up to date, else (re)compute.
+        /// </summary>
+        /// <returns>The hash code</returns>
+        public virtual int GetUnsequencedHashCode()
+        {
+            if (iUnSequencedHashCodeStamp == stamp)
+                return iUnSequencedHashCode;
+
+            iUnSequencedHashCode = ComputeHashCode(this, itemequalityComparer);
+            iUnSequencedHashCodeStamp = stamp;
+            return iUnSequencedHashCode;
+        }
+
+
+        /// <summary>
+        /// Check if the contents of otherCollection is equal to the contents of this
+        /// in the unsequenced sense.  Uses the item equality comparer of this collection
+        /// </summary>
+        /// <param name="otherCollection">The collection to compare to.</param>
+        /// <returns>True if  equal</returns>
+        public virtual bool UnsequencedEquals(ICollection<T> otherCollection)
+        {
+            return otherCollection != null && StaticEquals((ICollection<T>)this, otherCollection, itemequalityComparer);
+        }
+
+
+        /// <summary>
+        /// Check if the collection has been modified since a specified time, expressed as a stamp value.
+        /// </summary>
+        /// <exception cref="CollectionModifiedException"> if this collection has been updated 
+        /// since a target time</exception>
+        /// <param name="thestamp">The stamp identifying the target time</param>
+        protected virtual void modifycheck(int thestamp)
+        {
+            if (stamp != thestamp)
+                throw new CollectionModifiedException();
+        }
+
+
+        /// <summary>
+        /// Check if it is valid to perform update operations, and if so increment stamp.
+        /// </summary>
+        /// <exception cref="ReadOnlyCollectionException">If collection is read-only</exception>
+        protected virtual void updatecheck()
+        {
+            if (isReadOnlyBase)
+                throw new ReadOnlyCollectionException();
+
+            stamp++;
+        }
+
+        #endregion
+
+        #region ICollection<T> members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>True if this collection is read only</value>
+        public virtual bool IsReadOnly { get { return isReadOnlyBase; } }
+
+        #endregion
+
+        #region ICollectionValue<T> members
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The size of this collection</value>
+        public override int Count { get { return size; } }
+
+        /// <summary>
+        /// The value is symbolic indicating the type of asymptotic complexity
+        /// in terms of the size of this collection (worst-case or amortized as
+        /// relevant).
+        /// </summary>
+        /// <value>A characterization of the speed of the 
+        /// <code>Count</code> property in this collection.</value>
+        public override Speed CountSpeed { get { return Speed.Constant; } }
+
+
+        #endregion
+
+        #region IExtensible<T> members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return itemequalityComparer; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>True if this collection is empty</value>
+        public override bool IsEmpty { get { return size == 0; } }
+
+        #endregion
+
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    [Serializable]
+    public abstract class DirectedCollectionBase<T> : CollectionBase<T>, IDirectedCollectionValue<T>
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="itemequalityComparer"></param>
+        /// <param name = "memoryType">The type of memory for the enumerator used to iterate the collection</param>
+        protected DirectedCollectionBase(SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType) : base(itemequalityComparer, memoryType) { }
+        /// <summary>
+        /// <code>Forwards</code> if same, else <code>Backwards</code>
+        /// </summary>
+        /// <value>The enumeration direction relative to the original collection.</value>
+        public virtual EnumerationDirection Direction { get { return EnumerationDirection.Forwards; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public abstract IDirectedCollectionValue<T> Backwards();
+
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in this collection and return the first one in enumeration order.
+        /// </summary>
+        /// <param name="predicate">A delegate 
+        /// (<see cref="T:Func`2"/> with <code>R == bool</code>) defining the predicate</param>
+        /// <param name="item"></param>
+        /// <returns>True is such an item exists</returns>
+        public virtual bool FindLast(Func<T, bool> predicate, out T item)
+        {
+            foreach (T jtem in Backwards())
+                if (predicate(jtem))
+                {
+                    item = jtem;
+                    return true;
+                }
+            item = default(T);
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// A generic dictionary class based on a hash set class <see cref="T:C5.HashSet`1"/>. 
+    /// </summary>
+    [Serializable]
+    public class HashDictionary<K, V> : DictionaryBase<K, V>, IDictionary<K, V>
+    {
+        /// <summary>
+        /// Create a hash dictionary using a default equalityComparer for the keys.
+        /// Initial capacity of internal table will be 16 entries and threshold for 
+        /// expansion is 66% fill.
+        /// </summary>
+        public HashDictionary(MemoryType memoryType = MemoryType.Normal) : this(EqualityComparer<K>.Default, memoryType) { }
+
+        /// <summary>
+        /// Create a hash dictionary using a custom equalityComparer for the keys.
+        /// Initial capacity of internal table will be 16 entries and threshold for 
+        /// expansion is 66% fill.
+        /// </summary>
+        /// <param name="keyequalityComparer">The external key equalitySCG.Comparer</param>
+        /// <param name="memoryType">The memory type of the enumerator used to iterate the collection</param>
+        public HashDictionary(SCG.IEqualityComparer<K> keyequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(keyequalityComparer, memoryType)
+        {
+            pairs = new HashSet<KeyValuePair<K, V>>(new KeyValuePairEqualityComparer<K, V>(keyequalityComparer), memoryType);
+        }
+
+        /// <summary>
+        /// Create a hash dictionary using a custom equalityComparer and prescribing the 
+        /// initial size of the dictionary and a non-default threshold for internal table expansion.
+        /// </summary>
+        /// <param name="capacity">The initial capacity. Will be rounded upwards to nearest
+        /// power of 2, at least 16.</param>
+        /// <param name="fill">The expansion threshold. Must be between 10% and 90%.</param>
+        /// <param name="keyequalityComparer">The external key equalitySCG.Comparer</param>
+        /// <param name="memoryType">The memory type of the enumerator used to iterate the collection</param>
+        public HashDictionary(int capacity, double fill, SCG.IEqualityComparer<K> keyequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(keyequalityCompar

<TRUNCATED>

[39/58] [abbrv] lucenenet git commit: Ported Grouping.GroupingSearchTest and fixed several bugs.

Posted by ni...@apache.org.
Ported Grouping.GroupingSearchTest and fixed several bugs.


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

Branch: refs/heads/grouping
Commit: 28cd391216597828674b90ad477966326a5e34f9
Parents: 0a137be
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Wed Nov 2 23:08:22 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:55 2016 +0700

----------------------------------------------------------------------
 .../AbstractFirstPassGroupingCollector.cs       |  13 +-
 .../AbstractSecondPassGroupingCollector.cs      |  16 ++-
 .../BlockGroupingCollector.cs                   |  19 +--
 .../FunctionSecondPassGroupingCollector.cs      |   2 +-
 src/Lucene.Net.Grouping/GroupingSearch.cs       |  74 ++++++++++--
 .../Term/TermSecondPassGroupingCollector.cs     |   7 +-
 .../AllGroupsCollectorTest.cs                   |  18 ++-
 .../GroupingSearchTest.cs                       | 120 +++++++++----------
 .../Lucene.Net.Tests.Grouping.csproj            |   1 +
 9 files changed, 157 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
index 0fb682d..c7f6e52 100644
--- a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
@@ -1,11 +1,9 @@
-\ufeffusing Lucene.Net.Search;
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Support;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Lucene.Net.Index;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -77,7 +75,7 @@ namespace Lucene.Net.Search.Grouping
             }
 
             spareSlot = topNGroups;
-            groupMap = new Dictionary<TGroupValue, CollectedSearchGroup<TGroupValue>>(topNGroups);
+            groupMap = new HashMap<TGroupValue, CollectedSearchGroup<TGroupValue>>(topNGroups);
         }
 
         /// <summary>
@@ -188,9 +186,8 @@ namespace Lucene.Net.Search.Grouping
             // under null group)?
             TGroupValue groupValue = GetDocGroupValue(doc);
 
-            CollectedSearchGroup<TGroupValue> group = groupMap[groupValue];
-
-            if (group == null)
+            CollectedSearchGroup<TGroupValue> group;
+            if (!groupMap.TryGetValue(groupValue, out group))
             {
 
                 // First time we are seeing this group, or, we've seen

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
index 41b5837..6364d90 100644
--- a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
@@ -1,10 +1,8 @@
-\ufeffusing Lucene.Net.Search;
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Support;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Lucene.Net.Index;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -21,19 +19,19 @@ namespace Lucene.Net.Search.Grouping
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
-    public abstract class AbstractSecondPassGroupingCollector<TGroupValue> : Collector
+    public abstract class AbstractSecondPassGroupingCollector<TGroupValue> : Collector, IAbstractSecondPassGroupingCollector<TGroupValue>
     {
         protected readonly IDictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>> groupMap;
         private readonly int maxDocsPerGroup;
         protected AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>[] groupDocs;
-        private readonly IEnumerable<SearchGroup<TGroupValue>> groups;
+        private readonly IEnumerable<ISearchGroup<TGroupValue>> groups;
         private readonly Sort withinGroupSort;
         private readonly Sort groupSort;
 
         private int totalHitCount;
         private int totalGroupedHitCount;
 
-        public AbstractSecondPassGroupingCollector(IEnumerable<SearchGroup<TGroupValue>> groups, Sort groupSort, Sort withinGroupSort,
+        public AbstractSecondPassGroupingCollector(IEnumerable<ISearchGroup<TGroupValue>> groups, Sort groupSort, Sort withinGroupSort,
                                                    int maxDocsPerGroup, bool getScores, bool getMaxScores, bool fillSortFields)
         {
 
@@ -47,7 +45,7 @@ namespace Lucene.Net.Search.Grouping
             this.withinGroupSort = withinGroupSort;
             this.groups = groups;
             this.maxDocsPerGroup = maxDocsPerGroup;
-            groupMap = new Dictionary<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>>(groups.Count());
+            groupMap = new HashMap<TGroupValue, AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue>>(groups.Count());
 
             foreach (SearchGroup<TGroupValue> group in groups)
             {
@@ -116,7 +114,7 @@ namespace Lucene.Net.Search.Grouping
             return false;
         }
 
-        public TopGroups<TGroupValue> GetTopGroups(int withinGroupOffset)
+        public ITopGroups<TGroupValue> GetTopGroups(int withinGroupOffset)
         {
             GroupDocs<TGroupValue>[] groupDocsResult = new GroupDocs<TGroupValue>[groups.Count()];
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
index 2a82993..c7fd34c 100644
--- a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
@@ -1,12 +1,8 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -330,7 +326,12 @@ namespace Lucene.Net.Search.Grouping
          *  @param fillSortFields If true then the Comparable
          *     values for the sort fields will be set
          */
-        public TopGroups<T> GetTopGroups<T>(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
+        public ITopGroups<object> GetTopGroups(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
+        {
+            return GetTopGroups<object>(withinGroupSort, groupOffset, withinGroupOffset, maxDocsPerGroup, fillSortFields);
+        }
+
+        public ITopGroups<TGroupValue> GetTopGroups<TGroupValue>(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
         {
 
             //if (queueFull) {
@@ -350,7 +351,7 @@ namespace Lucene.Net.Search.Grouping
 
             float maxScore = float.MinValue;
 
-            GroupDocs<T>[] groups = new GroupDocs<T>[groupQueue.Size() - groupOffset];
+            GroupDocs<TGroupValue>[] groups = new GroupDocs<TGroupValue>[groupQueue.Size() - groupOffset];
             for (int downTo = groupQueue.Size() - groupOffset - 1; downTo >= 0; downTo--)
             {
                 OneGroup og = groupQueue.Pop();
@@ -406,11 +407,11 @@ namespace Lucene.Net.Search.Grouping
 
                 // TODO: we could aggregate scores across children
                 // by Sum/Avg instead of passing NaN:
-                groups[downTo] = new GroupDocs<T>(float.NaN,
+                groups[downTo] = new GroupDocs<TGroupValue>(float.NaN,
                                                        topDocs.MaxScore,
                                                        og.count,
                                                        topDocs.ScoreDocs,
-                                                       default(T),
+                                                       default(TGroupValue),
                                                        groupSortValues);
                 maxScore = Math.Max(maxScore, topDocs.MaxScore);
             }
@@ -423,7 +424,7 @@ namespace Lucene.Net.Search.Grouping
             }
             */
 
-            return new TopGroups<T>(new TopGroups<T>(groupSort.GetSort(),
+            return new TopGroups<TGroupValue>(new TopGroups<TGroupValue>(groupSort.GetSort(),
                                                withinGroupSort == null ? null : withinGroupSort.GetSort(),
                                                totalHitCount, totalGroupedHitCount, groups, maxScore),
                                  totalGroupCount);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
index 23f04b0..ec1fccb 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
@@ -33,7 +33,7 @@ namespace Lucene.Net.Search.Grouping.Function
         /// <param name="groupByVS">The <see cref="ValueSource"/> to group by</param>
         /// <param name="vsContext">The value source context</param>
         /// <exception cref="IOException">When I/O related errors occur</exception>
-        public FunctionSecondPassGroupingCollector(ICollection<SearchGroup<MutableValue>> searchGroups, 
+        public FunctionSecondPassGroupingCollector(IEnumerable<ISearchGroup<MutableValue>> searchGroups, 
             Sort groupSort, Sort withinGroupSort, int maxDocsPerGroup, bool getScores, bool getMaxScores, 
             bool fillSortFields, ValueSource groupByVS, IDictionary /* Map<?, ?> */ vsContext)
             : base(searchGroups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Grouping/GroupingSearch.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupingSearch.cs b/src/Lucene.Net.Grouping/GroupingSearch.cs
index 56554f6..c9353d8 100644
--- a/src/Lucene.Net.Grouping/GroupingSearch.cs
+++ b/src/Lucene.Net.Grouping/GroupingSearch.cs
@@ -1,6 +1,4 @@
 \ufeffusing Lucene.Net.Queries.Function;
-using Lucene.Net.Search;
-using Lucene.Net.Search.Grouping;
 using Lucene.Net.Search.Grouping.Function;
 using Lucene.Net.Search.Grouping.Terms;
 using Lucene.Net.Util;
@@ -8,9 +6,6 @@ using Lucene.Net.Util.Mutable;
 using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -41,7 +36,7 @@ namespace Lucene.Net.Search.Grouping
         private bool allGroupHeads;
         private int initialSize = 128;
 
-        private IList /* Collection<?> */ matchingGroups;
+        private ICollection /* Collection<?> */ matchingGroups;
         private Bits matchingGroupHeads;
 
         /**
@@ -97,6 +92,11 @@ namespace Lucene.Net.Search.Grouping
          * @return the grouped result as a {@link TopGroups} instance
          * @throws IOException If any I/O related errors occur
          */
+        public ITopGroups<object> Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+        {
+            return Search<object>(searcher, null, query, groupOffset, groupLimit);
+        }
+
         public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
         {
             return Search<TGroupValue>(searcher, null, query, groupOffset, groupLimit);
@@ -113,6 +113,26 @@ namespace Lucene.Net.Search.Grouping
          * @return the grouped result as a {@link TopGroups} instance
          * @throws IOException If any I/O related errors occur
          */
+        public ITopGroups<object> Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        {
+            if (groupFunction != null)
+            {
+                return GroupByFieldOrFunction<MutableValue>(searcher, filter, query, groupOffset, groupLimit);
+            }
+            else if (groupField != null)
+            {
+                return GroupByFieldOrFunction<BytesRef>(searcher, filter, query, groupOffset, groupLimit);
+            }
+            else if (groupEndDocs != null)
+            {
+                return GroupByDocBlock<object>(searcher, filter, query, groupOffset, groupLimit);
+            }
+            else
+            {
+                throw new InvalidOperationException("Either groupField, groupFunction or groupEndDocs must be set."); // This can't happen...
+            }
+        }
+
         public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             if (groupField != null || groupFunction != null)
@@ -121,7 +141,7 @@ namespace Lucene.Net.Search.Grouping
             }
             else if (groupEndDocs != null)
             {
-                return (TopGroups<TGroupValue>)GroupByDocBlock<TGroupValue>(searcher, filter, query, groupOffset, groupLimit);
+                return GroupByDocBlock<TGroupValue>(searcher, filter, query, groupOffset, groupLimit);
             }
             else
             {
@@ -129,6 +149,19 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
+        //protected ITopGroups<object> GroupByFieldOrFunction(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        //{
+        //    // LUCENENET TODO: Perhaps there is a better way to infer type without resorting to hard-coding them here, but
+        //    // the original GroupByFieldOrFunction is already aware of the underlying type based on the FirstPassGroupingCollector
+        //    // and SecondPassGroupingCollector.
+        //    if (groupFunction != null)
+        //    {
+        //        return GroupByFieldOrFunction<MutableValue>(searcher, filter, query, groupOffset, groupLimit);
+        //    }
+
+        //    return GroupByFieldOrFunction<BytesRef>(searcher, filter, query, groupOffset, groupLimit);
+        //}
+
         protected ITopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             int topN = groupOffset + groupLimit;
@@ -247,20 +280,28 @@ namespace Lucene.Net.Search.Grouping
             IAbstractSecondPassGroupingCollector<TGroupValue> secondPassCollector;
             if (groupFunction != null)
             {
-                secondPassCollector = (IAbstractSecondPassGroupingCollector<TGroupValue>)new FunctionSecondPassGroupingCollector(topSearchGroups as ICollection<SearchGroup<MutableValue>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext);
+                secondPassCollector = new FunctionSecondPassGroupingCollector(topSearchGroups as IEnumerable<ISearchGroup<MutableValue>>, 
+                    groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext)
+                    as IAbstractSecondPassGroupingCollector<TGroupValue>;
             }
             else
             {
-                secondPassCollector = (IAbstractSecondPassGroupingCollector<TGroupValue>)new TermSecondPassGroupingCollector(groupField, topSearchGroups as ICollection<SearchGroup<BytesRef>>, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
+                secondPassCollector = new TermSecondPassGroupingCollector(groupField, topSearchGroups as IEnumerable<ISearchGroup<BytesRef>>, 
+                    groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields)
+                    as IAbstractSecondPassGroupingCollector<TGroupValue>;
             }
 
             if (cachedCollector != null && cachedCollector.Cached)
             {
-                cachedCollector.Replay((Collector)secondPassCollector);
+                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                cachedCollector.Replay(secondPassCollector as Collector);
             }
             else
             {
-                searcher.Search(query, filter, (Collector)secondPassCollector);
+                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                searcher.Search(query, filter, secondPassCollector as Collector);
             }
 
             if (allGroups)
@@ -273,13 +314,13 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        protected ITopGroups<T> GroupByDocBlock<T>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+        protected ITopGroups<TGroupValue> GroupByDocBlock<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             int topN = groupOffset + groupLimit;
             BlockGroupingCollector c = new BlockGroupingCollector(groupSort, topN, includeScores, groupEndDocs);
             searcher.Search(query, filter, c);
             int topNInsideGroup = groupDocsOffset + groupDocsLimit;
-            return c.GetTopGroups<T>(sortWithinGroup, groupOffset, groupDocsOffset, topNInsideGroup, fillSortFields);
+            return c.GetTopGroups<TGroupValue>(sortWithinGroup, groupOffset, groupDocsOffset, topNInsideGroup, fillSortFields);
         }
 
         /**
@@ -443,6 +484,13 @@ namespace Lucene.Net.Search.Grouping
             return (ICollection<T>)matchingGroups;
         }
 
+        // LUCENENET specific used to get the groups if the type is unknown (since the above
+        // method will crash if the wrong type is used)
+        public ICollection GetAllMatchingGroups()
+        {
+            return matchingGroups;
+        }
+
         /**
          * Whether to compute all group heads (most relevant document per group) matching the query.
          * <p/>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
index da70372..c9de6c1 100644
--- a/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermSecondPassGroupingCollector.cs
@@ -1,11 +1,6 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Util;
-using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {
@@ -22,7 +17,7 @@ namespace Lucene.Net.Search.Grouping.Terms
         private SortedDocValues index;
         private readonly string groupField;
 
-        public TermSecondPassGroupingCollector(string groupField, ICollection<SearchGroup<BytesRef>> groups, Sort groupSort, Sort withinGroupSort,
+        public TermSecondPassGroupingCollector(string groupField, IEnumerable<ISearchGroup<BytesRef>> groups, Sort groupSort, Sort withinGroupSort,
                                                int maxDocsPerGroup, bool getScores, bool getMaxScores, bool fillSortFields)
                   : base(groups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields)
         {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
index c76a4da..32bdbc1 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
@@ -88,16 +88,22 @@ namespace Lucene.Net.Search.Grouping
             IndexSearcher indexSearcher = NewSearcher(w.Reader);
             w.Dispose();
 
-            AbstractAllGroupsCollector allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
-            indexSearcher.Search(new TermQuery(new Term("content", "random")), allGroupsCollector);
+            IAbstractAllGroupsCollector<object> allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "random")), allGroupsCollector as Collector);
             assertEquals(4, allGroupsCollector.GroupCount);
 
             allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
-            indexSearcher.Search(new TermQuery(new Term("content", "some")), allGroupsCollector);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "some")), allGroupsCollector as Collector);
             assertEquals(3, allGroupsCollector.GroupCount);
 
             allGroupsCollector = CreateRandomCollector(groupField, canUseIDV);
-            indexSearcher.Search(new TermQuery(new Term("content", "blob")), allGroupsCollector);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Term("content", "blob")), allGroupsCollector as Collector);
             assertEquals(2, allGroupsCollector.GroupCount);
 
             indexSearcher.IndexReader.Dispose();
@@ -113,9 +119,9 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private AbstractAllGroupsCollector CreateRandomCollector(string groupField, bool canUseIDV)
+        private IAbstractAllGroupsCollector<object> CreateRandomCollector(string groupField, bool canUseIDV)
         {
-            AbstractAllGroupsCollector selected;
+            IAbstractAllGroupsCollector<object> selected;
             if (Random().nextBoolean())
             {
                 selected = new TermAllGroupsCollector(groupField);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
index 8f49614..0b80e2e 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
@@ -8,10 +8,8 @@ using Lucene.Net.Util;
 using Lucene.Net.Util.Mutable;
 using NUnit.Framework;
 using System;
+using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -19,7 +17,7 @@ namespace Lucene.Net.Search.Grouping
     {
         // Tests some very basic usages...
         [Test]
-        public void testBasic()
+        public virtual void TestBasic()
         {
 
             string groupField = "author";
@@ -37,21 +35,21 @@ namespace Lucene.Net.Search.Grouping
             List<Document> documents = new List<Document>();
             // 0
             Document doc = new Document();
-            addGroupField(doc, groupField, "author1", canUseIDV);
+            AddGroupField(doc, groupField, "author1", canUseIDV);
             doc.Add(new TextField("content", "random text", Field.Store.YES));
             doc.Add(new Field("id", "1", customType));
             documents.Add(doc);
 
             // 1
             doc = new Document();
-            addGroupField(doc, groupField, "author1", canUseIDV);
+            AddGroupField(doc, groupField, "author1", canUseIDV);
             doc.Add(new TextField("content", "some more random text", Field.Store.YES));
             doc.Add(new Field("id", "2", customType));
             documents.Add(doc);
 
             // 2
             doc = new Document();
-            addGroupField(doc, groupField, "author1", canUseIDV);
+            AddGroupField(doc, groupField, "author1", canUseIDV);
             doc.Add(new TextField("content", "some more random textual data", Field.Store.YES));
             doc.Add(new Field("id", "3", customType));
             doc.Add(new StringField("groupend", "x", Field.Store.NO));
@@ -61,7 +59,7 @@ namespace Lucene.Net.Search.Grouping
 
             // 3
             doc = new Document();
-            addGroupField(doc, groupField, "author2", canUseIDV);
+            AddGroupField(doc, groupField, "author2", canUseIDV);
             doc.Add(new TextField("content", "some random text", Field.Store.YES));
             doc.Add(new Field("id", "4", customType));
             doc.Add(new StringField("groupend", "x", Field.Store.NO));
@@ -69,14 +67,14 @@ namespace Lucene.Net.Search.Grouping
 
             // 4
             doc = new Document();
-            addGroupField(doc, groupField, "author3", canUseIDV);
+            AddGroupField(doc, groupField, "author3", canUseIDV);
             doc.Add(new TextField("content", "some more random text", Field.Store.YES));
             doc.Add(new Field("id", "5", customType));
             documents.Add(doc);
 
             // 5
             doc = new Document();
-            addGroupField(doc, groupField, "author3", canUseIDV);
+            AddGroupField(doc, groupField, "author3", canUseIDV);
             doc.Add(new TextField("content", "random", Field.Store.YES));
             doc.Add(new Field("id", "6", customType));
             doc.Add(new StringField("groupend", "x", Field.Store.NO));
@@ -96,58 +94,58 @@ namespace Lucene.Net.Search.Grouping
             w.Dispose();
 
             Sort groupSort = Sort.RELEVANCE;
-            GroupingSearch groupingSearch = createRandomGroupingSearch(groupField, groupSort, 5, canUseIDV);
+            GroupingSearch groupingSearch = CreateRandomGroupingSearch(groupField, groupSort, 5, canUseIDV);
 
-            var groups = groupingSearch.Search(indexSearcher, (Filter)null, new TermQuery(new Index.Term("content", "random")), 0, 10);
+            ITopGroups<object> groups = groupingSearch.Search(indexSearcher, (Filter)null, new TermQuery(new Index.Term("content", "random")), 0, 10);
 
-            assertEquals(7, groups.totalHitCount);
-            assertEquals(7, groups.totalGroupedHitCount);
-            assertEquals(4, groups.groups.length);
+            assertEquals(7, groups.TotalHitCount);
+            assertEquals(7, groups.TotalGroupedHitCount);
+            assertEquals(4, groups.Groups.Length);
 
             // relevance order: 5, 0, 3, 4, 1, 2, 6
 
             // the later a document is added the higher this docId
             // value
-            GroupDocs <?> group = groups.groups[0];
-            compareGroupValue("author3", group);
-            assertEquals(2, group.scoreDocs.length);
-            assertEquals(5, group.scoreDocs[0].doc);
-            assertEquals(4, group.scoreDocs[1].doc);
-            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
-
-            group = groups.groups[1];
-            compareGroupValue("author1", group);
-            assertEquals(3, group.scoreDocs.length);
-            assertEquals(0, group.scoreDocs[0].doc);
-            assertEquals(1, group.scoreDocs[1].doc);
-            assertEquals(2, group.scoreDocs[2].doc);
-            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
-            assertTrue(group.scoreDocs[1].score > group.scoreDocs[2].score);
-
-            group = groups.groups[2];
-            compareGroupValue("author2", group);
-            assertEquals(1, group.scoreDocs.length);
-            assertEquals(3, group.scoreDocs[0].doc);
-
-            group = groups.groups[3];
-            compareGroupValue(null, group);
-            assertEquals(1, group.scoreDocs.length);
-            assertEquals(6, group.scoreDocs[0].doc);
+            var group = groups.Groups[0];
+            CompareGroupValue("author3", group);
+            assertEquals(2, group.ScoreDocs.Length);
+            assertEquals(5, group.ScoreDocs[0].Doc);
+            assertEquals(4, group.ScoreDocs[1].Doc);
+            assertTrue(group.ScoreDocs[0].Score > group.ScoreDocs[1].Score);
+
+            group = groups.Groups[1];
+            CompareGroupValue("author1", group);
+            assertEquals(3, group.ScoreDocs.Length);
+            assertEquals(0, group.ScoreDocs[0].Doc);
+            assertEquals(1, group.ScoreDocs[1].Doc);
+            assertEquals(2, group.ScoreDocs[2].Doc);
+            assertTrue(group.ScoreDocs[0].Score > group.ScoreDocs[1].Score);
+            assertTrue(group.ScoreDocs[1].Score > group.ScoreDocs[2].Score);
+
+            group = groups.Groups[2];
+            CompareGroupValue("author2", group);
+            assertEquals(1, group.ScoreDocs.Length);
+            assertEquals(3, group.ScoreDocs[0].Doc);
+
+            group = groups.Groups[3];
+            CompareGroupValue(null, group);
+            assertEquals(1, group.ScoreDocs.Length);
+            assertEquals(6, group.ScoreDocs[0].Doc);
 
             Filter lastDocInBlock = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Index.Term("groupend", "x"))));
             groupingSearch = new GroupingSearch(lastDocInBlock);
             groups = groupingSearch.Search(indexSearcher, null, new TermQuery(new Index.Term("content", "random")), 0, 10);
 
-            assertEquals(7, groups.totalHitCount);
-            assertEquals(7, groups.totalGroupedHitCount);
-            assertEquals(4, groups.totalGroupCount.longValue());
-            assertEquals(4, groups.groups.length);
+            assertEquals(7, groups.TotalHitCount);
+            assertEquals(7, groups.TotalGroupedHitCount);
+            assertEquals(4, groups.TotalGroupCount.GetValueOrDefault());
+            assertEquals(4, groups.Groups.Length);
 
             indexSearcher.IndexReader.Dispose();
             dir.Dispose();
         }
 
-        private void addGroupField(Document doc, string groupField, string value, bool canUseIDV)
+        private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV)
         {
             doc.Add(new TextField(groupField, value, Field.Store.YES));
             if (canUseIDV)
@@ -156,34 +154,34 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void compareGroupValue(string expected, GroupDocs<?> group)
+        private void CompareGroupValue(string expected, IGroupDocs<object> group)
         {
             if (expected == null)
             {
-                if (group.groupValue == null)
+                if (group.GroupValue == null)
                 {
                     return;
                 }
-                else if (group.groupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
+                else if (group.GroupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
                 {
                     return;
                 }
-                else if (((BytesRef)group.groupValue).length == 0)
+                else if (((BytesRef)group.GroupValue).Length == 0)
                 {
                     return;
                 }
                 fail();
             }
 
-            if (group.groupValue.GetType().IsAssignableFrom(typeof(BytesRef)))
+            if (group.GroupValue.GetType().IsAssignableFrom(typeof(BytesRef)))
             {
-                assertEquals(new BytesRef(expected), group.groupValue);
+                assertEquals(new BytesRef(expected), group.GroupValue);
             }
-            else if (group.groupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
+            else if (group.GroupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
             {
                 MutableValueStr v = new MutableValueStr();
-                v.value = new BytesRef(expected);
-                assertEquals(v, group.groupValue);
+                v.Value = new BytesRef(expected);
+                assertEquals(v, group.GroupValue);
             }
             else
             {
@@ -191,13 +189,13 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private GroupingSearch createRandomGroupingSearch(String groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
+        private GroupingSearch CreateRandomGroupingSearch(String groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
         {
             GroupingSearch groupingSearch;
             if (Random().nextBoolean())
             {
                 ValueSource vs = new BytesRefFieldSource(groupField);
-                groupingSearch = new GroupingSearch(vs, new Dictionary());
+                groupingSearch = new GroupingSearch(vs, new Hashtable());
             }
             else
             {
@@ -216,7 +214,7 @@ namespace Lucene.Net.Search.Grouping
         }
 
         [Test]
-        public void testSetAllGroups()
+        public virtual void TestSetAllGroups()
         {
             Directory dir = NewDirectory();
             RandomIndexWriter w = new RandomIndexWriter(
@@ -233,11 +231,11 @@ namespace Lucene.Net.Search.Grouping
 
             GroupingSearch gs = new GroupingSearch("group");
             gs.SetAllGroups(true);
-            TopGroups <?> groups = gs.Search(indexSearcher, null, new TermQuery(new Index.Term("group", "foo")), 0, 10);
-            assertEquals(1, groups.totalHitCount);
+            ITopGroups<object> groups = gs.Search(indexSearcher, null, new TermQuery(new Index.Term("group", "foo")), 0, 10);
+            assertEquals(1, groups.TotalHitCount);
             //assertEquals(1, groups.totalGroupCount.intValue());
-            assertEquals(1, groups.totalGroupedHitCount);
-            assertEquals(1, gs.GetAllMatchingGroups().size());
+            assertEquals(1, groups.TotalGroupedHitCount);
+            assertEquals(1, gs.GetAllMatchingGroups().Count);
             indexSearcher.IndexReader.Dispose();
             dir.Dispose();
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/28cd3912/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
index 806839d..cc96210 100644
--- a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
+++ b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
@@ -48,6 +48,7 @@
     <Compile Include="AllGroupHeadsCollectorTest.cs" />
     <Compile Include="AllGroupsCollectorTest.cs" />
     <Compile Include="GroupFacetCollectorTest.cs" />
+    <Compile Include="GroupingSearchTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <ItemGroup>


[51/58] [abbrv] lucenenet git commit: Grouping: Test code cleanup to verify API

Posted by ni...@apache.org.
Grouping: Test code cleanup to verify API


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

Branch: refs/heads/grouping
Commit: d0838cc3706f93a36557e1aa783f0af523aeace2
Parents: 3881180
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 23:51:21 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:20 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Grouping/SearchGroup.cs          | 14 +++++++
 src/Lucene.Net.Grouping/TopGroups.cs            | 14 ++++++-
 .../AllGroupHeadsCollectorTest.cs               |  9 ++---
 .../GroupFacetCollectorTest.cs                  | 25 ++++++------
 .../GroupingSearchTest.cs                       |  4 +-
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs   | 41 +++++++++-----------
 6 files changed, 64 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d0838cc3/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index a225f3c..23140bc 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -54,6 +54,18 @@ namespace Lucene.Net.Search.Grouping
         {
             return GroupValue != null ? GroupValue.GetHashCode() : 0;
         }
+    }
+
+    /// <summary>
+    /// LUCENENET specific class used to nest types to mimic the syntax used 
+    /// by Lucene (that is, without specifying the generic closing type of <see cref="SearchGroup{TGroupValue}"/>)
+    /// </summary>
+    public class SearchGroup
+    {
+        /// <summary>
+        /// Prevent direct creation
+        /// </summary>
+        private SearchGroup() { }
 
         private class ShardIter<T>
         {
@@ -361,6 +373,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
+
         /** Merges multiple collections of top groups, for example
          *  obtained from separate index shards.  The provided
          *  groupSort must match how the groups were sorted, and
@@ -383,6 +396,7 @@ namespace Lucene.Net.Search.Grouping
         }
     }
 
+
     /// <summary>
     /// LUCENENET specific interface used to provide covariance
     /// with the TGroupValue type

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d0838cc3/src/Lucene.Net.Grouping/TopGroups.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/TopGroups.cs b/src/Lucene.Net.Grouping/TopGroups.cs
index 54a9547..d66439d 100644
--- a/src/Lucene.Net.Grouping/TopGroups.cs
+++ b/src/Lucene.Net.Grouping/TopGroups.cs
@@ -77,6 +77,18 @@ namespace Lucene.Net.Search.Grouping
             MaxScore = oldTopGroups.MaxScore;
             TotalGroupCount = totalGroupCount;
         }
+    }
+
+    /// <summary>
+    /// LUCENENET specific class used to nest types to mimic the syntax used 
+    /// by Lucene (that is, without specifying the generic closing type of <see cref="TopGroups{TGroupValue}"/>)
+    /// </summary>
+    public class TopGroups
+    {
+        /// <summary>
+        /// Prevent direct creation
+        /// </summary>
+        private TopGroups() { }
 
         /// <summary>
         /// How the GroupDocs score (if any) should be merged. </summary>
@@ -148,7 +160,7 @@ namespace Lucene.Net.Search.Grouping
                     totalGroupCount += shard.TotalGroupCount;
                 }
             }
-            
+
             var mergedGroupDocs = new GroupDocs<T>[numGroups];
 
             TopDocs[] shardTopDocs = new TopDocs[shardGroups.Length];

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d0838cc3/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index 0f1ddb2..c7cac67 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -30,9 +30,9 @@ namespace Lucene.Net.Search.Grouping
             Directory dir = NewDirectory();
             RandomIndexWriter w = new RandomIndexWriter(
                 Random(),
-            dir,
-            NewIndexWriterConfig(TEST_VERSION_CURRENT,
-                new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+                dir,
+                NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                    new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
             bool canUseIDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             FieldInfo.DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
 
@@ -343,7 +343,7 @@ namespace Lucene.Net.Search.Grouping
                         string searchTerm = "real" + Random().nextInt(3);
                         bool sortByScoreOnly = Random().nextBoolean();
                         Sort sortWithinGroup = GetRandomSort(sortByScoreOnly);
-                        var allGroupHeadsCollector = CreateRandomCollector("group", sortWithinGroup, canUseIDV, valueType);
+                        AbstractAllGroupHeadsCollector allGroupHeadsCollector = CreateRandomCollector("group", sortWithinGroup, canUseIDV, valueType);
                         s.Search(new TermQuery(new Term("content", searchTerm)), allGroupHeadsCollector);
                         int[] expectedGroupHeads = CreateExpectedGroupHeads(searchTerm, groupDocs, sortWithinGroup, sortByScoreOnly, fieldIdToDocID);
                         int[] actualGroupHeads = allGroupHeadsCollector.RetrieveGroupHeads();
@@ -660,7 +660,6 @@ namespace Lucene.Net.Search.Grouping
                 this.sort3 = sort3;
                 this.content = content;
             }
-
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d0838cc3/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
index dda2cdb..e50c91b 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
@@ -74,8 +74,7 @@ namespace Lucene.Net.Search.Grouping
             AbstractGroupFacetCollector groupedAirportFacetCollector = null;
             TermGroupFacetCollector.GroupedFacetResult airportResult = null;
 
-            foreach (int limit in new int[] { 2, 10, 100, int.MaxValue
-    })
+            foreach (int limit in new int[] { 2, 10, 100, int.MaxValue })
             {
                 // any of these limits is plenty for the data we have
 
@@ -407,7 +406,7 @@ namespace Lucene.Net.Search.Grouping
                     searcher.Search(new TermQuery(new Term("content", searchTerm)), groupFacetCollector);
                     TermGroupFacetCollector.GroupedFacetResult actualFacetResult = groupFacetCollector.MergeSegmentResults(size, minCount, orderByCount);
 
-                    List<TermGroupFacetCollector.FacetEntry> expectedFacetEntries = expectedFacetResult.getFacetEntries();
+                    List<TermGroupFacetCollector.FacetEntry> expectedFacetEntries = expectedFacetResult.GetFacetEntries();
                     List<TermGroupFacetCollector.FacetEntry> actualFacetEntries = actualFacetResult.GetFacetEntries(offset, limit);
 
                     if (VERBOSE)
@@ -428,8 +427,8 @@ namespace Lucene.Net.Search.Grouping
                         Console.WriteLine("Order by count: " + orderByCount);
 
                         Console.WriteLine("\n=== Expected: \n");
-                        Console.WriteLine("Total count " + expectedFacetResult.getTotalCount());
-                        Console.WriteLine("Total missing count " + expectedFacetResult.getTotalMissingCount());
+                        Console.WriteLine("Total count " + expectedFacetResult.TotalCount);
+                        Console.WriteLine("Total missing count " + expectedFacetResult.TotalMissingCount);
                         int counter = 0;
                         foreach (TermGroupFacetCollector.FacetEntry expectedFacetEntry in expectedFacetEntries)
                         {
@@ -457,8 +456,8 @@ namespace Lucene.Net.Search.Grouping
                         Console.WriteLine("\n===================================================================================");
                     }
 
-                    assertEquals(expectedFacetResult.getTotalCount(), actualFacetResult.TotalCount);
-                    assertEquals(expectedFacetResult.getTotalMissingCount(), actualFacetResult.TotalMissingCount);
+                    assertEquals(expectedFacetResult.TotalCount, actualFacetResult.TotalCount);
+                    assertEquals(expectedFacetResult.TotalMissingCount, actualFacetResult.TotalMissingCount);
                     assertEquals(expectedFacetEntries.size(), actualFacetEntries.size());
                     for (int i = 0; i < expectedFacetEntries.size(); i++)
                     {
@@ -587,7 +586,7 @@ namespace Lucene.Net.Search.Grouping
             docNoGroupNoFacet.Add(content);
 
             // LUCENENET NOTE: TreeSet (the class used in Java) allows duplicate keys. However, SortedSet seems to work,
-            // and based on the name of the variable, presuming the keys are meant to be unique.
+            // and based on the name of the variable, presuming the entries are meant to be unique.
             ISet<string> uniqueFacetValues = new SortedSet<string>(new ComparerAnonymousHelper1());
 
             // LUCENENET NOTE: Need HashMap here because of null keys
@@ -881,17 +880,17 @@ namespace Lucene.Net.Search.Grouping
                 this.facetEntries = facetEntries;
             }
 
-            public int getTotalCount()
+            public int TotalCount
             {
-                return totalCount;
+                get { return totalCount; }
             }
 
-            public int getTotalMissingCount()
+            public int TotalMissingCount
             {
-                return totalMissingCount;
+                get { return totalMissingCount; }
             }
 
-            public List<TermGroupFacetCollector.FacetEntry> getFacetEntries()
+            public List<TermGroupFacetCollector.FacetEntry> GetFacetEntries()
             {
                 return facetEntries;
             }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d0838cc3/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
index 2971a52..49b56e6 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
@@ -106,7 +106,7 @@ namespace Lucene.Net.Search.Grouping
 
             // the later a document is added the higher this docId
             // value
-            var group = groups.Groups[0];
+            IGroupDocs<object> group = groups.Groups[0];
             CompareGroupValue("author3", group);
             assertEquals(2, group.ScoreDocs.Length);
             assertEquals(5, group.ScoreDocs[0].Doc);
@@ -189,7 +189,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private GroupingSearch CreateRandomGroupingSearch(String groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
+        private GroupingSearch CreateRandomGroupingSearch(string groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
         {
             GroupingSearch groupingSearch;
             if (Random().nextBoolean())

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d0838cc3/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index 6098887..1ce5f0e 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -99,17 +99,17 @@ namespace Lucene.Net.Search.Grouping
                 groupField += "_dv";
             }
 
-            IAbstractFirstPassGroupingCollector<IComparable> c1 = CreateRandomFirstPassCollector(groupField, groupSort, 10);
+            IAbstractFirstPassGroupingCollector<object> c1 = CreateRandomFirstPassCollector(groupField, groupSort, 10);
             // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
             // so this cast is not necessary. Consider eliminating the Collector abstract class.
             indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c1 as Collector);
 
-            IAbstractSecondPassGroupingCollector<IComparable> c2 = CreateSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, true, true);
+            IAbstractSecondPassGroupingCollector<object> c2 = CreateSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, true, true);
             // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
             // so this cast is not necessary. Consider eliminating the Collector abstract class.
             indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c2 as Collector);
 
-            ITopGroups<IComparable> groups = c2.GetTopGroups(0);
+            ITopGroups<object> groups = c2.GetTopGroups(0);
             assertFalse(float.IsNaN(groups.MaxScore));
 
             assertEquals(7, groups.TotalHitCount);
@@ -120,7 +120,7 @@ namespace Lucene.Net.Search.Grouping
 
             // the later a document is added the higher this docId
             // value
-            IGroupDocs<IComparable> group = groups.Groups[0];
+            IGroupDocs<object> group = groups.Groups[0];
             CompareGroupValue("author3", group);
             assertEquals(2, group.ScoreDocs.Length);
             assertEquals(5, group.ScoreDocs[0].Doc);
@@ -159,9 +159,9 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private IAbstractFirstPassGroupingCollector<IComparable> CreateRandomFirstPassCollector(string groupField, Sort groupSort, int topDocs)
+        private IAbstractFirstPassGroupingCollector<object> CreateRandomFirstPassCollector(string groupField, Sort groupSort, int topDocs)
         {
-            IAbstractFirstPassGroupingCollector<IComparable> selected;
+            IAbstractFirstPassGroupingCollector<object> selected;
             if (Random().nextBoolean())
             {
                 ValueSource vs = new BytesRefFieldSource(groupField);
@@ -318,8 +318,9 @@ namespace Lucene.Net.Search.Grouping
             }
             else if (typeof(FunctionFirstPassGroupingCollector).IsAssignableFrom(c.GetType()))
             {
-                // LUCENENET TODO: Can we remove this cast?
-                var mutableValueGroups = c.GetTopGroups(groupOffset, fillFields) as IEnumerable<ISearchGroup<MutableValue>>;
+                // LUCENENET NOTE: This is IEnumerable instead of ICollection because it 
+                // needs to be covariant to mimic the wildcard generics in Java
+                IEnumerable<ISearchGroup<MutableValue>> mutableValueGroups = ((FunctionFirstPassGroupingCollector)c).GetTopGroups(groupOffset, fillFields);
                 if (mutableValueGroups == null)
                 {
                     return null;
@@ -362,9 +363,6 @@ namespace Lucene.Net.Search.Grouping
 
         internal class GroupDoc
         {
-            private static int instanceIndex;
-            internal readonly int instanceId;
-
             internal readonly int id;
             internal readonly BytesRef group;
             internal readonly BytesRef sort1;
@@ -376,8 +374,6 @@ namespace Lucene.Net.Search.Grouping
 
             public GroupDoc(int id, BytesRef group, BytesRef sort1, BytesRef sort2, string content)
             {
-                this.instanceId = instanceIndex++;
-
                 this.id = id;
                 this.group = group;
                 this.sort1 = sort1;
@@ -1026,11 +1022,11 @@ namespace Lucene.Net.Search.Grouping
                         {
                             Console.WriteLine("  groupField=" + groupField);
                         }
-                        IAbstractFirstPassGroupingCollector<IComparable> c1 = CreateRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
+                        IAbstractFirstPassGroupingCollector<object> c1 = CreateRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
                         CachingCollector cCache;
                         Collector c;
 
-                        IAbstractAllGroupsCollector<IComparable> allGroupsCollector;
+                        IAbstractAllGroupsCollector<object> allGroupsCollector;
                         if (doAllGroups)
                         {
                             allGroupsCollector = CreateAllGroupsCollector(c1, groupField);
@@ -1126,6 +1122,8 @@ namespace Lucene.Net.Search.Grouping
                         }
 
                         // Get 1st pass top groups
+                        // LUCENENET NOTE: This is IEnumerable rather than ICollection because we need it to be
+                        // covariant in order to mimic Java's wildcard generics
                         IEnumerable<ISearchGroup<BytesRef>> topGroups = GetSearchGroups(c1, groupOffset, fillFields);
                         ITopGroups<BytesRef> groupsResult;
                         if (VERBOSE)
@@ -1149,7 +1147,7 @@ namespace Lucene.Net.Search.Grouping
                         ValueHolder<bool> idvBasedImplsUsedSharded = new ValueHolder<bool>(false);
                         TopGroups<BytesRef> topGroupsShards = SearchShards(s, shards.subSearchers, query, groupSort, docSort,
                            groupOffset, topNGroups, docOffset, docsPerGroup, getScores, getMaxScores, canUseIDV, preFlex, idvBasedImplsUsedSharded);
-                        IAbstractSecondPassGroupingCollector<IComparable> c2;
+                        IAbstractSecondPassGroupingCollector<object> c2;
                         if (topGroups != null)
                         {
 
@@ -1450,8 +1448,8 @@ namespace Lucene.Net.Search.Grouping
             // Run 1st pass collector to get top groups per shard
             Weight w = topSearcher.CreateNormalizedWeight(query);
             List<IEnumerable<ISearchGroup<BytesRef>>> shardGroups = new List<IEnumerable<ISearchGroup<BytesRef>>>();
-            List<IAbstractFirstPassGroupingCollector<IComparable>> firstPassGroupingCollectors = new List<IAbstractFirstPassGroupingCollector<IComparable>>();
-            IAbstractFirstPassGroupingCollector<IComparable> firstPassCollector = null;
+            List<IAbstractFirstPassGroupingCollector<object>> firstPassGroupingCollectors = new List<IAbstractFirstPassGroupingCollector<object>>();
+            IAbstractFirstPassGroupingCollector<object> firstPassCollector = null;
             bool shardsCanUseIDV;
             if (canUseIDV)
             {
@@ -1513,7 +1511,7 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-            ICollection<SearchGroup<BytesRef>> mergedTopGroups = SearchGroup<BytesRef>.Merge(shardGroups, groupOffset, topNGroups, groupSort);
+            ICollection<SearchGroup<BytesRef>> mergedTopGroups = SearchGroup.Merge(shardGroups, groupOffset, topNGroups, groupSort);
             if (VERBOSE)
             {
                 Console.WriteLine(" top groups merged:");
@@ -1537,7 +1535,7 @@ namespace Lucene.Net.Search.Grouping
                 ITopGroups<BytesRef>[] shardTopGroups = new ITopGroups<BytesRef>[subSearchers.Length];
                 for (int shardIDX = 0; shardIDX < subSearchers.Length; shardIDX++)
                 {
-                    IAbstractSecondPassGroupingCollector<IComparable> secondPassCollector = CreateSecondPassCollector(firstPassGroupingCollectors[shardIDX],
+                    IAbstractSecondPassGroupingCollector<object> secondPassCollector = CreateSecondPassCollector(firstPassGroupingCollectors[shardIDX],
                         groupField, mergedTopGroups, groupSort, docSort, docOffset + topNDocs, getScores, getMaxScores, true);
                     // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
                     // so this cast is not necessary. Consider eliminating the Collector abstract class.
@@ -1553,8 +1551,7 @@ namespace Lucene.Net.Search.Grouping
                     }
                 }
 
-                // LUCENENET TODO: Put Merge() in a TopGroups class
-                TopGroups<BytesRef> mergedGroups = TopGroups<BytesRef>.Merge(shardTopGroups, groupSort, docSort, docOffset, topNDocs, TopGroups<BytesRef>.ScoreMergeMode.None);
+                TopGroups<BytesRef> mergedGroups = TopGroups.Merge(shardTopGroups, groupSort, docSort, docOffset, topNDocs, TopGroups.ScoreMergeMode.None);
                 if (VERBOSE)
                 {
                     Console.WriteLine(" " + mergedGroups.Groups.Length + " merged groups:");


[06/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/ArrayList.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/ArrayList.cs b/src/Lucene.Net.Tests/core/Support/C5/ArrayList.cs
new file mode 100644
index 0000000..bcf446f
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/ArrayList.cs
@@ -0,0 +1,2248 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.C5
+{
+    /// <summary>
+    /// A list collection based on a plain dynamic array data structure.
+    /// Expansion of the internal array is performed by doubling on demand. 
+    /// The internal array is only shrinked by the Clear method. 
+    ///
+    /// <i>When the FIFO property is set to false this class works fine as a stack of T.
+    /// When the FIFO property is set to true the class will function as a (FIFO) queue
+    /// but very inefficiently, use a LinkedList (<see cref="T:C5.LinkedList`1"/>) instead.</i>
+    /// </summary>
+    [Serializable]
+    public class ArrayList<T> : ArrayBase<T>, IList<T>, IStack<T>, IQueue<T>
+    {
+        #region Fields
+
+        /// <summary>
+        /// Has this list or view not been invalidated by some operation (by someone calling Dispose())
+        /// </summary>
+        bool isValid = true;
+
+        //TODO: wonder if we should save some memory on none-view situations by 
+        //      putting these three fields into a single ref field?
+        /// <summary>
+        /// The underlying list if we are a view, null else.
+        /// </summary>
+        ArrayList<T> underlying;
+        WeakViewList<ArrayList<T>> views;
+        WeakViewList<ArrayList<T>>.Node myWeakReference;
+
+        /// <summary>
+        /// The size of the underlying list.
+        /// </summary>
+        int underlyingsize { get { return (underlying ?? this).size; } }
+
+        /// <summary>
+        /// The underlying field of the FIFO property
+        /// </summary>
+        bool fIFO = false;
+
+        #endregion
+        #region Events
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }
+
+        /*
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <value></value>
+            public override event CollectionChangedHandler<T> CollectionChanged
+            {
+              add
+              {
+                if (underlying == null)
+                  base.CollectionChanged += value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+              remove
+              {
+                if (underlying == null)
+                  base.CollectionChanged -= value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <value></value>
+            public override event CollectionClearedHandler<T> CollectionCleared
+            {
+              add
+              {
+                if (underlying == null)
+                  base.CollectionCleared += value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+              remove
+              {
+                if (underlying == null)
+                  base.CollectionCleared -= value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <value></value>
+            public override event ItemsAddedHandler<T> ItemsAdded
+            {
+              add
+              {
+                if (underlying == null)
+                  base.ItemsAdded += value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+              remove
+              {
+                if (underlying == null)
+                  base.ItemsAdded -= value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <value></value>
+            public override event ItemInsertedHandler<T> ItemInserted
+            {
+              add
+              {
+                if (underlying == null)
+                  base.ItemInserted += value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+              remove
+              {
+                if (underlying == null)
+                  base.ItemInserted -= value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <value></value>
+            public override event ItemsRemovedHandler<T> ItemsRemoved
+            {
+              add
+              {
+                if (underlying == null)
+                  base.ItemsRemoved += value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+              remove
+              {
+                if (underlying == null)
+                  base.ItemsRemoved -= value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+            }
+
+            /// <summary>
+            /// 
+            /// </summary>
+            /// <value></value>
+            public override event ItemRemovedAtHandler<T> ItemRemovedAt
+            {
+              add
+              {
+                if (underlying == null)
+                  base.ItemRemovedAt += value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+              remove
+              {
+                if (underlying == null)
+                  base.ItemRemovedAt -= value;
+                else
+                  throw new UnlistenableEventException("Can't listen to a view");
+              }
+            }
+
+              */
+
+        #endregion
+        #region Util
+
+        bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }
+
+        /// <summary>
+        /// Increment or decrement the private size fields
+        /// </summary>
+        /// <param name="delta">Increment (with sign)</param>
+        void addtosize(int delta)
+        {
+            size += delta;
+            if (underlying != null)
+                underlying.size += delta;
+        }
+
+        #region Array handling
+        /// <summary>
+        /// Double the size of the internal array.
+        /// </summary>
+        protected override void expand()
+        { expand(2 * array.Length, underlyingsize); }
+
+
+        /// <summary>
+        /// Expand the internal array, resetting the index of the first unused element.
+        /// </summary>
+        /// <param name="newcapacity">The new capacity (will be rounded upwards to a power of 2).</param>
+        /// <param name="newsize">The new count of </param>
+        protected override void expand(int newcapacity, int newsize)
+        {
+            if (underlying != null)
+                underlying.expand(newcapacity, newsize);
+            else
+            {
+                base.expand(newcapacity, newsize);
+                if (views != null)
+                    foreach (ArrayList<T> v in views)
+                        v.array = array;
+            }
+        }
+
+        #endregion
+
+        #region Checks
+        /// <summary>
+        /// Check if it is valid to perform updates and increment stamp if so.
+        /// </summary>
+        /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>
+        /// <exception cref="ReadOnlyCollectionException"> If check fails by this being a read only list.</exception>
+        protected override void updatecheck()
+        {
+            validitycheck();
+            base.updatecheck();
+            if (underlying != null)
+                underlying.stamp++;
+        }
+
+
+        /// <summary>
+        /// Check if we are a view that the underlying list has only been updated through us.
+        /// <para>This method should be called from enumerators etc to guard against 
+        /// modification of the base collection.</para>
+        /// </summary>
+        /// <exception cref="ViewDisposedException"> if check fails.</exception>
+        void validitycheck()
+        {
+            if (!isValid)
+                throw new ViewDisposedException();
+        }
+
+
+        /// <summary>
+        /// Check that the list has not been updated since a particular time.
+        /// <para>To be used by enumerators and range </para>
+        /// </summary>
+        /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>
+        /// <exception cref="CollectionModifiedException">If the list *has* been updated since that  time..</exception>
+        /// <param name="stamp">The stamp indicating the time.</param>
+        protected override void modifycheck(int stamp)
+        {
+            validitycheck();
+            if (this.stamp != stamp)
+                throw new CollectionModifiedException();
+        }
+
+        #endregion
+
+        #region Searching
+
+        /// <summary>
+        /// Internal version of IndexOf without modification checks.
+        /// </summary>
+        /// <param name="item">Item to look for</param>
+        /// <returns>The index of first occurrence</returns>
+        int indexOf(T item)
+        {
+            for (int i = 0; i < size; i++)
+                if (equals(item, array[offsetField + i]))
+                    return i;
+            return ~size;
+        }
+
+        /// <summary>
+        /// Internal version of LastIndexOf without modification checks.
+        /// </summary>
+        /// <param name="item">Item to look for</param>
+        /// <returns>The index of last occurrence</returns>
+        int lastIndexOf(T item)
+        {
+            for (int i = size - 1; i >= 0; i--)
+                if (equals(item, array[offsetField + i]))
+                    return i;
+            return ~size;
+        }
+        #endregion
+
+        #region Inserting
+
+        /// <summary>
+        /// Internal version of Insert with no modification checks.
+        /// </summary>
+        /// <param name="i">Index to insert at</param>
+        /// <param name="item">Item to insert</param>
+        protected override void InsertProtected(int i, T item)
+        {
+            baseinsert(i, item);
+        }
+
+        private void baseinsert(int i, T item)
+        {
+            if (underlyingsize == array.Length)
+                expand();
+            i += offsetField;
+            if (i < underlyingsize)
+                Array.Copy(array, i, array, i + 1, underlyingsize - i);
+            array[i] = item;
+            addtosize(1);
+            fixViewsAfterInsert(1, i);
+        }
+        #endregion
+
+        #region Removing
+
+        /// <summary>
+        /// Internal version of RemoveAt with no modification checks.
+        /// </summary>
+        /// <param name="i">Index to remove at</param>
+        /// <returns>The removed item</returns>
+        T removeAt(int i)
+        {
+            i += offsetField;
+            fixViewsBeforeSingleRemove(i);
+            T retval = array[i];
+            addtosize(-1);
+            if (underlyingsize > i)
+                Array.Copy(array, i + 1, array, i, underlyingsize - i);
+            array[underlyingsize] = default(T);
+
+            return retval;
+        }
+        #endregion
+
+        #region Indexing
+
+        #endregion
+
+        #region fixView utilities
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="added">The actual number of inserted nodes</param>
+        /// <param name="realInsertionIndex"></param>
+        void fixViewsAfterInsert(int added, int realInsertionIndex)
+        {
+            if (views != null)
+                foreach (ArrayList<T> view in views)
+                {
+                    if (view != this)
+                    {
+                        if (view.offsetField < realInsertionIndex && view.offsetField + view.size > realInsertionIndex)
+                            view.size += added;
+                        if (view.offsetField > realInsertionIndex || (view.offsetField == realInsertionIndex && view.size > 0))
+                            view.offsetField += added;
+                    }
+                }
+        }
+
+        void fixViewsBeforeSingleRemove(int realRemovalIndex)
+        {
+            if (views != null)
+                foreach (ArrayList<T> view in views)
+                {
+                    if (view != this)
+                    {
+                        if (view.offsetField <= realRemovalIndex && view.offsetField + view.size > realRemovalIndex)
+                            view.size--;
+                        if (view.offsetField > realRemovalIndex)
+                            view.offsetField--;
+                    }
+                }
+        }
+
+        /// <summary>
+        /// Fix offsets and sizes of other views before removing an interval from this 
+        /// </summary>
+        /// <param name="start">the start of the interval relative to the array/underlying</param>
+        /// <param name="count"></param>
+        void fixViewsBeforeRemove(int start, int count)
+        {
+            int clearend = start + count - 1;
+            if (views != null)
+                foreach (ArrayList<T> view in views)
+                {
+                    if (view == this)
+                        continue;
+                    int viewoffset = view.offsetField, viewend = viewoffset + view.size - 1;
+                    if (start < viewoffset)
+                    {
+                        if (clearend < viewoffset)
+                            view.offsetField = viewoffset - count;
+                        else
+                        {
+                            view.offsetField = start;
+                            view.size = clearend < viewend ? viewend - clearend : 0;
+                        }
+                    }
+                    else if (start <= viewend)
+                        view.size = clearend <= viewend ? view.size - count : start - viewoffset;
+                }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="otherOffset"></param>
+        /// <param name="otherSize"></param>
+        /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>
+        MutualViewPosition viewPosition(int otherOffset, int otherSize)
+        {
+            int end = offsetField + size, otherEnd = otherOffset + otherSize;
+            if (otherOffset >= end || otherEnd <= offsetField)
+                return MutualViewPosition.NonOverlapping;
+            if (size == 0 || (otherOffset <= offsetField && end <= otherEnd))
+                return MutualViewPosition.Contains;
+            if (otherSize == 0 || (offsetField <= otherOffset && otherEnd <= end))
+                return MutualViewPosition.ContainedIn;
+            return MutualViewPosition.Overlapping;
+        }
+
+        //TODO: make version that fits the new, more forgiving rules for disposing
+        void disposeOverlappingViews(bool reverse)
+        {
+            if (views != null)
+                foreach (ArrayList<T> view in views)
+                {
+                    if (view != this)
+                    {
+                        switch (viewPosition(view.offsetField, view.size))
+                        {
+                            case MutualViewPosition.ContainedIn:
+                                if (reverse)
+                                    view.offsetField = 2 * offsetField + size - view.size - view.offsetField;
+                                else
+                                    view.Dispose();
+                                break;
+                            case MutualViewPosition.Overlapping:
+                                view.Dispose();
+                                break;
+                            case MutualViewPosition.Contains:
+                            case MutualViewPosition.NonOverlapping:
+                                break;
+                        }
+                    }
+                }
+        }
+        #endregion
+
+        #endregion
+
+        #region Position, PositionComparer and ViewHandler nested types
+        [Serializable]
+        class PositionComparer : SCG.IComparer<Position>
+        {
+            public int Compare(Position a, Position b)
+            {
+                return a.index.CompareTo(b.index);
+            }
+        }
+        /// <summary>
+        /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for ArrayList?)
+        /// </summary>
+        struct Position
+        {
+            public readonly ArrayList<T> view;
+            public readonly int index;
+            public Position(ArrayList<T> view, bool left)
+            {
+                this.view = view;
+                index = left ? view.offsetField : view.offsetField + view.size - 1;
+            }
+            public Position(int index) { this.index = index; view = null; }
+        }
+
+        /// <summary>
+        /// Handle the update of (other) views during a multi-remove operation.
+        /// </summary>
+        struct ViewHandler
+        {
+            ArrayList<Position> leftEnds;
+            ArrayList<Position> rightEnds;
+            int leftEndIndex, rightEndIndex;
+            internal readonly int viewCount;
+            internal ViewHandler(ArrayList<T> list)
+            {
+                leftEndIndex = rightEndIndex = viewCount = 0;
+                leftEnds = rightEnds = null;
+                if (list.views != null)
+                    foreach (ArrayList<T> v in list.views)
+                        if (v != list)
+                        {
+                            if (leftEnds == null)
+                            {
+                                leftEnds = new ArrayList<Position>();
+                                rightEnds = new ArrayList<Position>();
+                            }
+                            leftEnds.Add(new Position(v, true));
+                            rightEnds.Add(new Position(v, false));
+                        }
+                if (leftEnds == null)
+                    return;
+                viewCount = leftEnds.Count;
+                leftEnds.Sort(new PositionComparer());
+                rightEnds.Sort(new PositionComparer());
+            }
+            /// <summary>
+            /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed
+            /// </summary>
+            /// <param name="removed"></param>
+            /// <param name="realindex"></param>
+            internal void skipEndpoints(int removed, int realindex)
+            {
+                if (viewCount > 0)
+                {
+                    Position endpoint;
+                    while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)
+                    {
+                        ArrayList<T> view = endpoint.view;
+                        view.offsetField = view.offsetField - removed;
+                        view.size += removed;
+                        leftEndIndex++;
+                    }
+                    while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)
+                    {
+                        endpoint.view.size -= removed;
+                        rightEndIndex++;
+                    }
+                }
+            }
+            internal void updateViewSizesAndCounts(int removed, int realindex)
+            {
+                if (viewCount > 0)
+                {
+                    Position endpoint;
+                    while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)
+                    {
+                        ArrayList<T> view = endpoint.view;
+                        view.offsetField = view.Offset - removed;
+                        view.size += removed;
+                        leftEndIndex++;
+                    }
+                    while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)
+                    {
+                        endpoint.view.size -= removed;
+                        rightEndIndex++;
+                    }
+                }
+            }
+        }
+        #endregion
+
+        #region Constructors
+        /// <summary>
+        /// Create an array list with default item equalityComparer and initial capacity 8 items and a Normal memory type
+        /// </summary>
+        public ArrayList() : this(8) { }
+
+
+        /// <summary>
+        /// Create an array list with default item equalityComparer and initial capacity 8 items.
+        /// </summary>
+        public ArrayList(MemoryType memoryType = MemoryType.Normal) : this(8, memoryType) { }
+
+
+        /// <summary>
+        /// Create an array list with external item equalityComparer and initial capacity 8 items.
+        /// </summary>
+        /// <param name="itemequalityComparer">The external item equalitySCG.Comparer</param>
+        /// <param name="memoryType"> The memory type strategy of the internal enumerator used to iterate over the collection</param>
+        public ArrayList(SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType = MemoryType.Normal) : this(8, itemequalityComparer, memoryType) { }
+
+
+        /// <summary>
+        /// Create an array list with default item equalityComparer and prescribed initial capacity.
+        /// </summary>
+        /// <param name="capacity">The prescribed capacity</param>
+        /// <param name="memoryType">The memory type strategy of the internal enumerator used to iterate over the collection</param>
+        public ArrayList(int capacity, MemoryType memoryType = MemoryType.Normal) : this(capacity, EqualityComparer<T>.Default, memoryType) { }
+
+
+        /// <summary>
+        /// Create an array list with external item equalityComparer and prescribed initial capacity.
+        /// </summary>
+        /// <param name="capacity">The prescribed capacity</param>
+        /// <param name="itemequalityComparer">The external item equalitySCG.Comparer</param>
+        /// <param name="memoryType">The memory type strategy of the internal enumerator used to iterate over the collection</param>
+        public ArrayList(int capacity, SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(capacity, itemequalityComparer, memoryType)
+        {
+
+        }
+
+        #endregion
+
+        #region IList<T> Members
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+        /// <value>The first item in this list.</value>
+        public virtual T First
+        {
+            get
+            {
+                validitycheck();
+                if (size == 0)
+                    throw new NoSuchItemException();
+
+                return array[offsetField];
+            }
+        }
+
+
+        /// <summary>
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+        /// <value>The last item in this list.</value>
+        public virtual T Last
+        {
+            get
+            {
+                validitycheck();
+                if (size == 0)
+                    throw new NoSuchItemException();
+
+                return array[offsetField + size - 1];
+            }
+        }
+
+
+        /// <summary>
+        /// Since <code>Add(T item)</code> always add at the end of the list,
+        /// this describes if list has FIFO or LIFO semantics.
+        /// </summary>
+        /// <value>True if the <code>Remove()</code> operation removes from the
+        /// start of the list, false if it removes from the end. The default for a new array list is false.</value>
+        public virtual bool FIFO
+        {
+            get { validitycheck(); return fIFO; }
+            set { updatecheck(); fIFO = value; }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public virtual bool IsFixedSize
+        {
+            get { validitycheck(); return false; }
+        }
+
+        /// <summary>
+        /// On this list, this indexer is read/write.
+        /// </summary>
+        /// <exception cref="IndexOutOfRangeException"> if index is negative or
+        /// &gt;= the size of the collection.</exception>
+        /// <value>The index'th item of this list.</value>
+        /// <param name="index">The index of the item to fetch or store.</param>
+        public virtual T this[int index]
+        {
+            get
+            {
+                validitycheck();
+                if (index < 0 || index >= size)
+                    throw new IndexOutOfRangeException();
+
+                return array[offsetField + index];
+            }
+            set
+            {
+                updatecheck();
+                if (index < 0 || index >= size)
+                    throw new IndexOutOfRangeException();
+                index += offsetField;
+                T item = array[index];
+
+                array[index] = value;
+
+                (underlying ?? this).raiseForSetThis(index, value, item);
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual Speed IndexingSpeed { get { return Speed.Constant; } }
+
+        /// <summary>
+        /// Insert an item at a specific index location in this list. 
+        ///</summary>
+        /// <exception cref="IndexOutOfRangeException"> if i is negative or
+        /// &gt; the size of the collection. </exception>
+        /// <param name="index">The index at which to insert.</param>
+        /// <param name="item">The item to insert.</param>
+        public virtual void Insert(int index, T item)
+        {
+            updatecheck();
+            if (index < 0 || index > size)
+                throw new IndexOutOfRangeException();
+
+            InsertProtected(index, item);
+            (underlying ?? this).raiseForInsert(index + offsetField, item);
+        }
+
+        /// <summary>
+        /// Insert an item at the end of a compatible view, used as a pointer.
+        /// <para>The <code>pointer</code> must be a view on the same list as
+        /// <code>this</code> and the endpoint of <code>pointer</code> must be
+        /// a valid insertion point of <code>this</code></para>
+        /// </summary>
+        /// <exception cref="IncompatibleViewException">If <code>pointer</code> 
+        /// is not a view on or the same list as <code>this</code></exception>
+        /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of 
+        ///  <code>pointer</code> is not inside <code>this</code></exception>
+        /// <exception cref="DuplicateNotAllowedException"> if the list has
+        /// <code>AllowsDuplicates==false</code> and the item is 
+        /// already in the list.</exception>
+        /// <param name="pointer"></param>
+        /// <param name="item"></param>
+        public void Insert(IList<T> pointer, T item)
+        {
+            if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))
+                throw new IncompatibleViewException();
+            Insert(pointer.Offset + pointer.Count - Offset, item);
+        }
+
+        /// <summary>
+        /// Insert into this list all items from an enumerable collection starting 
+        /// at a particular index.
+        /// </summary>
+        /// <exception cref="IndexOutOfRangeException"> if index is negative or
+        /// &gt; the size of the collection.</exception>
+        /// <param name="index">Index to start inserting at</param>
+        /// <param name="items">Items to insert</param>
+        public virtual void InsertAll(int index, SCG.IEnumerable<T> items)
+        {
+            updatecheck();
+            if (index < 0 || index > size)
+                throw new IndexOutOfRangeException();
+            index += offsetField;
+            int toadd = countItems(items);
+            if (toadd == 0)
+                return;
+            if (toadd + underlyingsize > array.Length)
+                expand(toadd + underlyingsize, underlyingsize);
+            if (underlyingsize > index)
+                Array.Copy(array, index, array, index + toadd, underlyingsize - index);
+            int i = index;
+            try
+            {
+
+                foreach (T item in items)
+                {
+                    array[i++] = item;
+                }
+            }
+            finally
+            {
+                int added = i - index;
+                if (added < toadd)
+                {
+                    Array.Copy(array, index + toadd, array, i, underlyingsize - index);
+                    Array.Clear(array, underlyingsize + added, toadd - added);
+                }
+                if (added > 0)
+                {
+                    addtosize(added);
+
+                    fixViewsAfterInsert(added, index);
+                    (underlying ?? this).raiseForInsertAll(index, added);
+                }
+            }
+        }
+        private void raiseForInsertAll(int index, int added)
+        {
+            if (ActiveEvents != 0)
+            {
+                if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)
+                    for (int j = index; j < index + added; j++)
+                    {
+                        raiseItemInserted(array[j], j);
+                        raiseItemsAdded(array[j], 1);
+                    }
+                raiseCollectionChanged();
+            }
+        }
+
+        /// <summary>
+        /// Insert an item at the front of this list;
+        /// </summary>
+        /// <param name="item">The item to insert.</param>
+        public virtual void InsertFirst(T item)
+        {
+            updatecheck();
+            InsertProtected(0, item);
+            (underlying ?? this).raiseForInsert(offsetField, item);
+        }
+
+        /// <summary>
+        /// Insert an item at the back of this list.
+        /// </summary>
+        /// <param name="item">The item to insert.</param>
+        public virtual void InsertLast(T item)
+        {
+            updatecheck();
+            InsertProtected(size, item);
+            (underlying ?? this).raiseForInsert(size - 1 + offsetField, item);
+        }
+
+
+        //NOTE: if the filter throws an exception, no result will be returned.
+        /// <summary>
+        /// Create a new list consisting of the items of this list satisfying a 
+        /// certain predicate.
+        /// <para>The new list will be of type ArrayList</para>
+        /// </summary>
+        /// <param name="filter">The filter delegate defining the predicate.</param>
+        /// <returns>The new list.</returns>
+        public virtual IList<T> FindAll(Func<T, bool> filter)
+        {
+            validitycheck();
+            int stamp = this.stamp;
+            ArrayList<T> res = new ArrayList<T>(itemequalityComparer);
+            int j = 0, rescap = res.array.Length;
+            for (int i = 0; i < size; i++)
+            {
+                T a = array[offsetField + i];
+                bool found = filter(a);
+                modifycheck(stamp);
+                if (found)
+                {
+                    if (j == rescap) res.expand(rescap = 2 * rescap, j);
+                    res.array[j++] = a;
+                }
+            }
+            res.size = j;
+
+            return res;
+        }
+
+        /// <summary>
+        /// Create a new list consisting of the results of mapping all items of this
+        /// list. The new list will use the default item equalityComparer for the item type V.
+        /// <para>The new list will be of type ArrayList</para>
+        /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The delegate defining the map.</param>
+        /// <returns>The new list.</returns>
+        public virtual IList<V> Map<V>(Func<T, V> mapper)
+        {
+            validitycheck();
+
+            ArrayList<V> res = new ArrayList<V>(size);
+
+            return map<V>(mapper, res);
+        }
+
+        /// <summary>
+        /// Create a new list consisting of the results of mapping all items of this
+        /// list. The new list will use a specified item equalityComparer for the item type.
+        /// <para>The new list will be of type ArrayList</para>
+        /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The delegate defining the map.</param>
+        /// <param name="itemequalityComparer">The item equalityComparer to use for the new list</param>
+        /// <returns>The new list.</returns>
+        public virtual IList<V> Map<V>(Func<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer)
+        {
+            validitycheck();
+
+            ArrayList<V> res = new ArrayList<V>(size, itemequalityComparer);
+
+            return map<V>(mapper, res);
+        }
+
+        private IList<V> map<V>(Func<T, V> mapper, ArrayList<V> res)
+        {
+            int stamp = this.stamp;
+            if (size > 0)
+                for (int i = 0; i < size; i++)
+                {
+                    V mappeditem = mapper(array[offsetField + i]);
+                    modifycheck(stamp);
+
+                    res.array[i] = mappeditem;
+                }
+            res.size = size;
+            return res;
+        }
+
+        /// <summary>
+        /// Remove one item from the list: from the front if <code>FIFO</code>
+        /// is true, else from the back.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+        /// <returns>The removed item.</returns>
+        public virtual T Remove()
+        {
+            updatecheck();
+            if (size == 0)
+                throw new NoSuchItemException("List is empty");
+
+            T item = removeAt(fIFO ? 0 : size - 1);
+            (underlying ?? this).raiseForRemove(item);
+            return item;
+        }
+
+        /// <summary>
+        /// Remove one item from the front of the list.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+        /// <returns>The removed item.</returns>
+        public virtual T RemoveFirst()
+        {
+            updatecheck();
+            if (size == 0)
+                throw new NoSuchItemException("List is empty");
+
+            T item = removeAt(0);
+            (underlying ?? this).raiseForRemoveAt(offsetField, item);
+            return item;
+        }
+
+
+        /// <summary>
+        /// Remove one item from the back of the list.
+        /// </summary>
+        /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+        /// <returns>The removed item.</returns>
+        public virtual T RemoveLast()
+        {
+            updatecheck();
+            if (size == 0)
+                throw new NoSuchItemException("List is empty");
+
+            T item = removeAt(size - 1);
+            (underlying ?? this).raiseForRemoveAt(size + offsetField, item);
+            return item;
+        }
+
+        /// <summary>
+        /// Create a list view on this list. 
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative
+        /// or the range does not fit within list.</exception>
+        /// <param name="start">The index in this list of the start of the view.</param>
+        /// <param name="count">The size of the view.</param>
+        /// <returns>The new list view.</returns>
+        public virtual IList<T> View(int start, int count)
+        {
+            validitycheck();
+            checkRange(start, count);
+            if (views == null)
+                views = new WeakViewList<ArrayList<T>>();
+            ArrayList<T> retval = (ArrayList<T>)MemberwiseClone();
+
+
+            retval.underlying = underlying != null ? underlying : this;
+            retval.offsetField = start + offsetField;
+            retval.size = count;
+            retval.myWeakReference = views.Add(retval);
+            return retval;
+        }
+
+        /// <summary>
+        /// Create a list view on this list containing the (first) occurrence of a particular item.
+        /// <para>Returns <code>null</code> if the item is not in this list.</para>
+        /// </summary>
+        /// <param name="item">The item to find.</param>
+        /// <returns>The new list view.</returns>
+        public virtual IList<T> ViewOf(T item)
+        {
+            int index = indexOf(item);
+            if (index < 0)
+                return null;
+            return View(index, 1);
+        }
+
+
+        /// <summary>
+        /// Create a list view on this list containing the last occurrence of a particular item. 
+        /// <para>Returns <code>null</code> if the item is not in this list.</para>
+        /// </summary>
+        /// <param name="item">The item to find.</param>
+        /// <returns>The new list view.</returns>
+        public virtual IList<T> LastViewOf(T item)
+        {
+            int index = lastIndexOf(item);
+            if (index < 0)
+                return null;
+            return View(index, 1);
+        }
+
+        /// <summary>
+        /// Null if this list is not a view.
+        /// </summary>
+        /// <value>Underlying list for view.</value>
+        public virtual IList<T> Underlying { get { return underlying; } }
+
+
+        /// <summary>
+        /// </summary>
+        /// <value>Offset for this list view or 0 for an underlying list.</value>
+        public virtual int Offset { get { return offsetField; } }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public virtual bool IsValid { get { return isValid; } }
+
+        /// <summary>
+        /// Slide this list view along the underlying list.
+        /// </summary>
+        /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"> if the operation
+        /// would bring either end of the view outside the underlying list.</exception>
+        /// <param name="offset">The signed amount to slide: positive to slide
+        /// towards the end.</param>
+        public virtual IList<T> Slide(int offset)
+        {
+            if (!TrySlide(offset, size))
+                throw new ArgumentOutOfRangeException();
+            return this;
+        }
+
+
+        /// <summary>
+        /// Slide this list view along the underlying list, changing its size.
+        /// </summary>
+        /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"> if the operation
+        /// would bring either end of the view outside the underlying list.</exception>
+        /// <param name="offset">The signed amount to slide: positive to slide
+        /// towards the end.</param>
+        /// <param name="size">The new size of the view.</param>
+        public virtual IList<T> Slide(int offset, int size)
+        {
+            if (!TrySlide(offset, size))
+                throw new ArgumentOutOfRangeException();
+            return this;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+        /// <param name="offset"></param>
+        /// <returns></returns>
+        public virtual bool TrySlide(int offset)
+        {
+            return TrySlide(offset, size);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+        /// <param name="offset"></param>
+        /// <param name="size"></param>
+        /// <returns></returns>
+        public virtual bool TrySlide(int offset, int size)
+        {
+            updatecheck();
+            if (underlying == null)
+                throw new NotAViewException("Not a view");
+
+            int newoffset = this.offsetField + offset;
+            int newsize = size;
+
+            if (newoffset < 0 || newsize < 0 || newoffset + newsize > underlyingsize)
+                return false;
+
+            this.offsetField = newoffset;
+            this.size = newsize;
+            return true;
+        }
+
+        /// <summary>
+        /// 
+        /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>
+        /// </summary>
+        /// <param name="otherView"></param>
+        /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>
+        /// <returns></returns>
+        public virtual IList<T> Span(IList<T> otherView)
+        {
+            if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))
+                throw new IncompatibleViewException();
+            if (otherView.Offset + otherView.Count - Offset < 0)
+                return null;
+            return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);
+        }
+
+        /// <summary>
+        /// Reverse the list so the items are in the opposite sequence order.
+        /// </summary>
+        public virtual void Reverse()
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            for (int i = 0, length = size / 2, end = offsetField + size - 1; i < length; i++)
+            {
+                T swap = array[offsetField + i];
+
+                array[offsetField + i] = array[end - i];
+                array[end - i] = swap;
+            }
+
+            //TODO: be more forgiving wrt. disposing
+            disposeOverlappingViews(true);
+            (underlying ?? this).raiseCollectionChanged();
+        }
+
+        /// <summary>
+        /// Check if this list is sorted according to the default sorting order
+        /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+        /// </summary>
+        /// <exception cref="NotComparableException">if T is not comparable</exception>
+        /// <returns>True if the list is sorted, else false.</returns>
+        public bool IsSorted() { return IsSorted(SCG.Comparer<T>.Default); }
+
+        /// <summary>
+        /// Check if this list is sorted according to a specific sorting order.
+        /// </summary>
+        /// <param name="c">The comparer defining the sorting order.</param>
+        /// <returns>True if the list is sorted, else false.</returns>
+        public virtual bool IsSorted(SCG.IComparer<T> c)
+        {
+            validitycheck();
+            for (int i = offsetField + 1, end = offsetField + size; i < end; i++)
+                if (c.Compare(array[i - 1], array[i]) > 0)
+                    return false;
+
+            return true;
+        }
+
+        /// <summary>
+        /// Sort the items of the list according to the default sorting order
+        /// for the item type T, as defined by the Comparer[T] class 
+        /// (<see cref="T:C5.Comparer`1"/>).
+        /// </summary>
+        /// <exception cref="InvalidOperationException">if T is not comparable</exception>
+        public virtual void Sort()
+        {
+            Sort(SCG.Comparer<T>.Default);
+        }
+
+
+        /// <summary>
+        /// Sort the items of the list according to a specific sorting order.
+        /// </summary>
+        /// <param name="comparer">The comparer defining the sorting order.</param>
+        public virtual void Sort(SCG.IComparer<T> comparer)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            Sorting.IntroSort<T>(array, offsetField, size, comparer);
+            disposeOverlappingViews(false);
+
+            (underlying ?? this).raiseCollectionChanged();
+        }
+
+
+        /// <summary>
+        /// Randomly shuffle the items of this list. 
+        /// </summary>
+        public virtual void Shuffle() { Shuffle(new Random()); }
+
+
+        /// <summary>
+        /// Shuffle the items of this list according to a specific random source.
+        /// </summary>
+        /// <param name="rnd">The random source.</param>
+        public virtual void Shuffle(Random rnd)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            for (int i = offsetField, top = offsetField + size, end = top - 1; i < end; i++)
+            {
+                int j = rnd.Next(i, top);
+                if (j != i)
+                {
+                    T tmp = array[i];
+                    array[i] = array[j];
+                    array[j] = tmp;
+                }
+            }
+            disposeOverlappingViews(false);
+
+            (underlying ?? this).raiseCollectionChanged();
+        }
+        #endregion
+
+        #region IIndexed<T> Members
+
+        /// <summary>
+        /// Search for an item in the list going forwards from the start.
+        /// </summary>
+        /// <param name="item">Item to search for.</param>
+        /// <returns>Index of item from start.</returns>
+        public virtual int IndexOf(T item) { validitycheck(); return indexOf(item); }
+
+
+        /// <summary>
+        /// Search for an item in the list going backwards from the end.
+        /// </summary>
+        /// <param name="item">Item to search for.</param>
+        /// <returns>Index of item from the end.</returns>
+        public virtual int LastIndexOf(T item) { validitycheck(); return lastIndexOf(item); }
+
+
+        /// <summary>
+        /// Remove the item at a specific position of the list.
+        /// </summary>
+        /// <exception cref="IndexOutOfRangeException"> if index is negative or
+        /// &gt;= the size of the collection.</exception>
+        /// <param name="index">The index of the item to remove.</param>
+        /// <returns>The removed item.</returns>
+        public virtual T RemoveAt(int index)
+        {
+            updatecheck();
+            if (index < 0 || index >= size)
+                throw new IndexOutOfRangeException("Index out of range for sequenced collection");
+
+            T item = removeAt(index);
+            (underlying ?? this).raiseForRemoveAt(offsetField + index, item);
+            return item;
+        }
+
+
+        /// <summary>
+        /// Remove all items in an index interval.
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException">If <code>start</code>
+        /// and <code>count</code> does not describe a valid interval in the list</exception> 
+        /// <param name="start">The index of the first item to remove.</param>
+        /// <param name="count">The number of items to remove.</param>
+        public virtual void RemoveInterval(int start, int count)
+        {
+            updatecheck();
+            if (count == 0)
+                return;
+            checkRange(start, count);
+            start += offsetField;
+            fixViewsBeforeRemove(start, count);
+
+            Array.Copy(array, start + count, array, start, underlyingsize - start - count);
+            addtosize(-count);
+            Array.Clear(array, underlyingsize, count);
+
+            (underlying ?? this).raiseForRemoveInterval(start, count);
+        }
+        void raiseForRemoveInterval(int start, int count)
+        {
+            if (ActiveEvents != 0)
+            {
+                raiseCollectionCleared(size == 0, count, start);
+                raiseCollectionChanged();
+            }
+        }
+        #endregion
+
+        #region ICollection<T> Members
+
+        /// <summary>
+        /// The value is symbolic indicating the type of asymptotic complexity
+        /// in terms of the size of this collection (worst-case or amortized as
+        /// relevant).
+        /// </summary>
+        /// <value>Speed.Linear</value>
+        public virtual Speed ContainsSpeed
+        {
+            get
+            {
+                return Speed.Linear;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public override int GetUnsequencedHashCode()
+        { validitycheck(); return base.GetUnsequencedHashCode(); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="that"></param>
+        /// <returns></returns>
+        public override bool UnsequencedEquals(ICollection<T> that)
+        { validitycheck(); return base.UnsequencedEquals(that); }
+
+        /// <summary>
+        /// Check if this collection contains (an item equivalent to according to the
+        /// itemequalityComparer) a particular value.
+        /// </summary>
+        /// <param name="item">The value to check for.</param>
+        /// <returns>True if the items is in this collection.</returns>
+        public virtual bool Contains(T item)
+        { validitycheck(); return indexOf(item) >= 0; }
+
+
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+        /// binary copy of) the actual value found.
+        /// </summary>
+        /// <param name="item">The value to look for.</param>
+        /// <returns>True if the items is in this collection.</returns>
+        public virtual bool Find(ref T item)
+        {
+            validitycheck();
+
+            int i;
+
+            if ((i = indexOf(item)) >= 0)
+            {
+                item = array[offsetField + i];
+                return true;
+            }
+
+            return false;
+        }
+
+
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, update the item in the collection 
+        /// to with a binary copy of the supplied value. This will only update the first 
+        /// mathching item.
+        /// </summary>
+        /// <param name="item">Value to update.</param>
+        /// <returns>True if the item was found and hence updated.</returns>
+        public virtual bool Update(T item)
+        {
+            T olditem;
+            return Update(item, out olditem);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public virtual bool Update(T item, out T olditem)
+        {
+            updatecheck();
+            int i;
+
+            if ((i = indexOf(item)) >= 0)
+            {
+                olditem = array[offsetField + i];
+                array[offsetField + i] = item;
+
+                (underlying ?? this).raiseForUpdate(item, olditem);
+                return true;
+            }
+
+            olditem = default(T);
+            return false;
+        }
+
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+        /// binary copy of) the actual value found. Else, add the item to the collection.
+        /// </summary>
+        /// <param name="item">The value to look for.</param>
+        /// <returns>True if the item was found (hence not added).</returns>
+        public virtual bool FindOrAdd(ref T item)
+        {
+            updatecheck();
+            if (Find(ref item))
+                return true;
+
+            Add(item);
+            return false;
+        }
+
+
+        /// <summary>
+        /// Check if this collection contains an item equivalent according to the
+        /// itemequalityComparer to a particular value. If so, update the item in the collection 
+        /// to with a binary copy of the supplied value. This will only update the first 
+        /// matching item.
+        /// </summary>
+        /// <param name="item">Value to update.</param>
+        /// <returns>True if the item was found and hence updated.</returns>
+        public virtual bool UpdateOrAdd(T item)
+        {
+            updatecheck();
+            if (Update(item))
+                return true;
+
+            Add(item);
+            return false;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public virtual bool UpdateOrAdd(T item, out T olditem)
+        {
+            updatecheck();
+            if (Update(item, out olditem))
+                return true;
+
+            Add(item);
+            olditem = default(T);
+            return false;
+        }
+
+        /// <summary>
+        /// Remove a particular item from this list. The item will be searched 
+        /// for from the end of the list if <code>FIFO == false</code> (the default), 
+        /// else from the start.
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        /// <returns>True if the item was found (and removed).</returns>
+        public virtual bool Remove(T item)
+        {
+            updatecheck();
+
+            int i = fIFO ? indexOf(item) : lastIndexOf(item);
+
+            if (i < 0)
+                return false;
+
+            T removeditem = removeAt(i);
+            (underlying ?? this).raiseForRemove(removeditem);
+            return true;
+        }
+
+
+        /// <summary>
+        /// Remove the first copy of a particular item from this collection if found.
+        /// If an item was removed, report a binary copy of the actual item removed in 
+        /// the argument. The item will be searched 
+        /// for from the end of the list if <code>FIFO == false</code> (the default), 
+        /// else from the start.
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        /// <param name="removeditem">The removed value.</param>
+        /// <returns>True if the item was found (and removed).</returns>
+        public virtual bool Remove(T item, out T removeditem)
+        {
+            updatecheck();
+
+            int i = fIFO ? indexOf(item) : lastIndexOf(item);
+
+            if (i < 0)
+            {
+                removeditem = default(T);
+                return false;
+            }
+
+            removeditem = removeAt(i);
+            (underlying ?? this).raiseForRemove(removeditem);
+            return true;
+        }
+
+
+        //TODO: remove from end or according to FIFO?
+        /// <summary>
+        /// Remove all items in another collection from this one, taking multiplicities into account.
+        /// Matching items will be removed from the front. Current implementation is not optimal.
+        /// </summary>
+        /// <param name="items">The items to remove.</param>
+        public virtual void RemoveAll(SCG.IEnumerable<T> items)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            //TODO: reactivate the old code for small sizes
+            HashBag<T> toremove = new HashBag<T>(itemequalityComparer);
+            toremove.AddAll(items);
+            if (toremove.Count == 0)
+                return;
+            RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+            bool mustFire = raiseHandler.MustFire;
+            ViewHandler viewHandler = new ViewHandler(this);
+            int j = offsetField;
+            int removed = 0;
+            int i = offsetField, end = offsetField + size;
+
+            while (i < end)
+            {
+                T item;
+                //pass by a stretch of nodes
+                while (i < end && !toremove.Contains(item = array[i]))
+                {
+                    //if (j<i)
+                    array[j] = item;
+                    i++; j++;
+                }
+                viewHandler.skipEndpoints(removed, i);
+                //Remove a stretch of nodes
+                while (i < end && toremove.Remove(item = array[i]))
+                {
+                    if (mustFire)
+                        raiseHandler.Remove(item);
+                    removed++;
+                    i++;
+                    viewHandler.updateViewSizesAndCounts(removed, i);
+                }
+            }
+            if (removed == 0)
+                return;
+            viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+            Array.Copy(array, offsetField + size, array, j, underlyingsize - offsetField - size);
+            addtosize(-removed);
+            Array.Clear(array, underlyingsize, removed);
+
+            if (mustFire)
+                raiseHandler.Raise();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="predicate"></param>
+        void RemoveAll(Func<T, bool> predicate)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+            bool mustFire = raiseHandler.MustFire;
+            ViewHandler viewHandler = new ViewHandler(this);
+            int j = offsetField;
+            int removed = 0;
+            int i = offsetField, end = offsetField + size;
+
+            while (i < end)
+            {
+                T item;
+                //pass by a stretch of nodes
+                while (i < end && !predicate(item = array[i]))
+                {
+                    updatecheck();
+
+                    //if (j<i)
+                    array[j] = item;
+                    i++; j++;
+                }
+                updatecheck();
+                viewHandler.skipEndpoints(removed, i);
+                //Remove a stretch of nodes
+                while (i < end && predicate(item = array[i]))
+                {
+                    updatecheck();
+
+                    if (mustFire)
+                        raiseHandler.Remove(item);
+                    removed++;
+                    i++;
+                    viewHandler.updateViewSizesAndCounts(removed, i);
+                }
+                updatecheck();
+            }
+            if (removed == 0)
+                return;
+            viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+            Array.Copy(array, offsetField + size, array, j, underlyingsize - offsetField - size);
+            addtosize(-removed);
+            Array.Clear(array, underlyingsize, removed);
+
+            if (mustFire)
+                raiseHandler.Raise();
+        }
+
+        /// <summary>
+        /// Remove all items from this collection, resetting internal array size.
+        /// </summary>
+        public override void Clear()
+        {
+            if (underlying == null)
+            {
+                updatecheck();
+                if (size == 0)
+                    return;
+                int oldsize = size;
+                fixViewsBeforeRemove(0, size);
+
+                array = new T[8];
+                size = 0;
+                (underlying ?? this).raiseForRemoveInterval(offsetField, oldsize);
+            }
+            else
+                RemoveInterval(0, size);
+        }
+
+        /// <summary>
+        /// Remove all items not in some other collection from this one, taking multiplicities into account.
+        /// Items are retained front first.  
+        /// </summary>
+        /// <param name="items">The items to retain.</param>
+        public virtual void RetainAll(SCG.IEnumerable<T> items)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            HashBag<T> toretain = new HashBag<T>(itemequalityComparer);
+            toretain.AddAll(items);
+            if (toretain.Count == 0)
+            {
+                Clear();
+                return;
+            }
+            RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+            bool mustFire = raiseHandler.MustFire;
+            ViewHandler viewHandler = new ViewHandler(this);
+            int j = offsetField;
+            int removed = 0;
+            int i = offsetField, end = offsetField + size;
+
+            while (i < end)
+            {
+                T item;
+                //pass by a stretch of nodes
+                while (i < end && toretain.Remove(item = array[i]))
+                {
+                    //if (j<i)
+                    array[j] = item;
+                    i++; j++;
+                }
+                viewHandler.skipEndpoints(removed, i);
+                //Remove a stretch of nodes
+                while (i < end && !toretain.Contains(item = array[i]))
+                {
+                    if (mustFire)
+                        raiseHandler.Remove(item);
+                    removed++;
+                    i++;
+                    viewHandler.updateViewSizesAndCounts(removed, i);
+                }
+            }
+            if (removed == 0)
+                return;
+            viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+            Array.Copy(array, offsetField + size, array, j, underlyingsize - offsetField - size);
+            addtosize(-removed);
+            Array.Clear(array, underlyingsize, removed);
+
+            raiseHandler.Raise();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="predicate"></param>
+        void RetainAll(Func<T, bool> predicate)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+            bool mustFire = raiseHandler.MustFire;
+            ViewHandler viewHandler = new ViewHandler(this);
+            int j = offsetField;
+            int removed = 0;
+            int i = offsetField, end = offsetField + size;
+
+            while (i < end)
+            {
+                T item;
+                //pass by a stretch of nodes
+                while (i < end && predicate(item = array[i]))
+                {
+                    updatecheck();
+
+                    //if (j<i)
+                    array[j] = item;
+                    i++; j++;
+                }
+                updatecheck();
+                viewHandler.skipEndpoints(removed, i);
+                //Remove a stretch of nodes
+                while (i < end && !predicate(item = array[i]))
+                {
+                    updatecheck();
+
+                    if (mustFire)
+                        raiseHandler.Remove(item);
+                    removed++;
+                    i++;
+                    viewHandler.updateViewSizesAndCounts(removed, i);
+                }
+                updatecheck();
+            }
+            if (removed == 0)
+                return;
+            viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+            Array.Copy(array, offsetField + size, array, j, underlyingsize - offsetField - size);
+            addtosize(-removed);
+            Array.Clear(array, underlyingsize, removed);
+
+            raiseHandler.Raise();
+        }
+
+
+        /// <summary>
+        /// Check if this collection contains all the values in another collection,
+        /// taking multiplicities into account.
+        /// Current implementation is not optimal.
+        /// </summary>
+        /// <param name="items">The </param>
+        /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+        public virtual bool ContainsAll(SCG.IEnumerable<T> items)
+        {
+            validitycheck();
+
+            //TODO: use aux hash bag to obtain linear time procedure
+            HashBag<T> tomatch = new HashBag<T>(itemequalityComparer);
+            tomatch.AddAll(items);
+            if (tomatch.Count == 0)
+                return true;
+            for (int i = offsetField, end = offsetField + size; i < end; i++)
+            {
+                tomatch.Remove(array[i]);
+                if (tomatch.Count == 0)
+                    return true;
+            }
+            return false;
+        }
+
+
+        /// <summary>
+        /// Count the number of items of the collection equal to a particular value.
+        /// Returns 0 if and only if the value is not in the collection.
+        /// </summary>
+        /// <param name="item">The value to count.</param>
+        /// <returns>The number of copies found.</returns>
+        public virtual int ContainsCount(T item)
+        {
+            validitycheck();
+
+            int count = 0;
+            for (int i = 0; i < size; i++)
+                if (equals(item, array[offsetField + i]))
+                    count++;
+            return count;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<T> UniqueItems()
+        {
+            HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+            hashbag.AddAll(this);
+            return hashbag.UniqueItems();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+        {
+            HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+            hashbag.AddAll(this);
+            return hashbag.ItemMultiplicities();
+        }
+
+
+
+
+
+        /// <summary>
+        /// Remove all items equal to a given one.
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        public virtual void RemoveAllCopies(T item)
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+            bool mustFire = raiseHandler.MustFire;
+            ViewHandler viewHandler = new ViewHandler(this);
+            int j = offsetField;
+            int removed = 0;
+            int i = offsetField, end = offsetField + size;
+            while (i < end)
+            {
+                //pass by a stretch of nodes
+                while (i < end && !equals(item, array[i]))
+                    array[j++] = array[i++];
+                viewHandler.skipEndpoints(removed, i);
+                //Remove a stretch of nodes
+                while (i < end && equals(item, array[i]))
+                {
+                    if (mustFire)
+                        raiseHandler.Remove(array[i]);
+                    removed++;
+                    i++;
+                    viewHandler.updateViewSizesAndCounts(removed, i);
+                }
+            }
+            if (removed == 0)
+                return;
+            viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+            Array.Copy(array, offsetField + size, array, j, underlyingsize - offsetField - size);
+            addtosize(-removed);
+            Array.Clear(array, underlyingsize, removed);
+            raiseHandler.Raise();
+        }
+
+
+        //TODO: check views
+        /// <summary>
+        /// Check the integrity of the internal data structures of this array list.
+        /// </summary>
+        /// <returns>True if check does not fail.</returns>
+        public override bool Check()
+        {
+            bool retval = true;
+
+            if (underlyingsize > array.Length)
+            {
+                Logger.Log(string.Format("underlyingsize ({0}) > array.Length ({1})", size, array.Length));
+                return false;
+            }
+
+            if (offsetField + size > underlyingsize)
+            {
+                Logger.Log(string.Format("offset({0})+size({1}) > underlyingsize ({2})", offsetField, size, underlyingsize));
+                return false;
+            }
+
+            if (offsetField < 0)
+            {
+                Logger.Log(string.Format("offset({0}) < 0", offsetField));
+                return false;
+            }
+
+            for (int i = 0; i < underlyingsize; i++)
+            {
+                if ((object)(array[i]) == null)
+                {
+                    Logger.Log(string.Format("Bad element: null at (base)index {0}", i));
+                    retval = false;
+                }
+            }
+
+            for (int i = underlyingsize, length = array.Length; i < length; i++)
+            {
+                if (!equals(array[i], default(T)))
+                {
+                    Logger.Log(string.Format("Bad element: != default(T) at (base)index {0}", i));
+                    retval = false;
+                }
+            }
+
+            {
+                ArrayList<T> u = underlying ?? this;
+                if (u.views != null)
+                    foreach (ArrayList<T> v in u.views)
+                    {
+                        if (u.array != v.array)
+                        {
+                            Logger.Log(string.Format("View from {0} of length has different base array than the underlying list", v.offsetField, v.size));
+                            retval = false;
+                        }
+                    }
+            }
+
+            return retval;
+        }
+
+        #endregion
+
+        #region IExtensible<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>True, indicating array list has bag semantics.</value>
+        public virtual bool AllowsDuplicates
+        {
+            get
+            {
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// By convention this is true for any collection with set semantics.
+        /// </summary>
+        /// <value>True if only one representative of a group of equal items 
+        /// is kept in the collection together with the total count.</value>
+        public virtual bool DuplicatesByCounting
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Add an item to end of this list.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
+        /// <returns>True</returns>
+        public virtual bool Add(T item)
+        {
+            updatecheck();
+
+            baseinsert(size, item);
+
+            (underlying ?? this).raiseForAdd(item);
+            return true;
+        }
+
+
+        /// <summary>
+        /// Add the elements from another collection to this collection.
+        /// </summary>
+        /// <param name="items"></param>
+        public virtual void AddAll(SCG.IEnumerable<T> items)
+        {
+            updatecheck();
+            int toadd = countItems(items);
+            if (toadd == 0)
+                return;
+
+            if (toadd + underlyingsize > array.Length)
+                expand(toadd + underlyingsize, underlyingsize);
+
+            int i = size + offsetField;
+            if (underlyingsize > i)
+                Array.Copy(array, i, array, i + toadd, underlyingsize - i);
+            try
+            {
+                foreach (T item in items)
+                {
+                    array[i++] = item;
+                }
+            }
+            finally
+            {
+                int added = i - size - offsetField;
+                if (added < toadd)
+                {
+                    Array.Copy(array, size + offsetField + toadd, array, i, underlyingsize - size - offsetField);
+                    Array.Clear(array, underlyingsize + added, toadd - added);
+                }
+                if (added > 0)
+                {
+                    addtosize(added);
+                    fixViewsAfterInsert(added, i - added);
+                    (underlying ?? this).raiseForAddAll(i - added, added);
+                }
+            }
+        }
+        private void raiseForAddAll(int start, int added)
+        {
+            if ((ActiveEvents & EventTypeEnum.Added) != 0)
+                for (int i = start, end = start + added; i < end; i++)
+                    raiseItemsAdded(array[i], 1);
+            raiseCollectionChanged();
+        }
+
+        #endregion
+
+        #region IDirectedEnumerable<T> Members
+
+        /// <summary>
+        /// Create a collection containing the same items as this collection, but
+        /// whose enumerator will enumerate the items backwards. The new collection
+        /// will become invalid if the original is modified. Method typically used as in
+        /// <code>foreach (T x in coll.Backwards()) {...}</code>
+        /// </summary>
+        /// <returns>The backwards collection.</returns>
+        IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+        #endregion
+
+        #region ICollectionValue<T> Members
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value>The number of items in this collection</value>
+        public override int Count { get { validitycheck(); return size; } }
+        #endregion
+
+        #region IEnumerable<T> Members
+        //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException)
+        /// <summary>
+        /// Create an enumerator for the collection
+        /// </summary>
+        /// <returns>The enumerator</returns>
+        public override SCG.IEnumerator<T> GetEnumerator()
+        {
+            validitycheck();
+            return base.GetEnumerator();
+        }
+        #endregion
+
+
+        #region IStack<T> Members
+
+        /// <summary>
+        /// Push an item to the top of the stack.
+        /// </summary>
+        /// <param name="item">The item</param>
+        public virtual void Push(T item)
+        {
+            InsertLast(item);
+        }
+
+        /// <summary>
+        /// Pop the item at the top of the stack from the stack.
+        /// </summary>
+        /// <returns>The popped item.</returns>
+        public virtual T Pop()
+        {
+            return RemoveLast();
+        }
+
+        #endregion
+
+        #region IQueue<T> Members
+
+        /// <summary>
+        /// Enqueue an item at the back of the queue. 
+        /// </summary>
+        /// <param name="item">The item</param>
+        public virtual void Enqueue(T item)
+        {
+            InsertLast(item);
+        }
+
+        /// <summary>
+        /// Dequeue an item from the front of the queue.
+        /// </summary>
+        /// <returns>The item</returns>
+        public virtual T Dequeue()
+        {
+            return RemoveFirst();
+        }
+
+        #endregion
+        #region IDisposable Members
+
+        /// <summary>
+        /// Invalidate this list. If a view, just invalidate the view. 
+        /// If not a view, invalidate the list and all views on it.
+        /// </summary>
+        public virtual void Dispose()
+        {
+            Dispose(false);
+        }
+
+        void Dispose(bool disposingUnderlying)
+        {
+            if (isValid)
+            {
+                if (underlying != null)
+                {
+                    isValid = false;
+                    if (!disposingUnderlying && views != null)
+                        views.Remove(myWeakReference);
+                    underlying = null;
+                    views = null;
+                    myWeakReference = null;
+                }
+                else
+                {
+                    //isValid = false;
+                    if (views != null)
+                        foreach (ArrayList<T> view in views)
+                            view.Dispose(true);
+                    Clear();
+                }
+            }
+        }
+
+        #endregion
+
+        #region ISerializable Members
+        /*
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="info"></param>
+    /// <param name="context"></param>
+    public ArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
+      this(info.GetInt32("sz"),(SCG.IEqualityComparer<T>)(info.GetValue("eq",typeof(SCG.IEqualityComparer<T>))))
+    {
+      size = info.GetInt32("sz");
+      for (int i = 0; i < size; i++)
+      {
+        array[i] = (T)(info.GetValue("elem" + i,typeof(T)));
+      }
+    
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="info"></param>
+    /// <param name="context"></param>
+    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+    {
+      info.AddValue("sz", size);
+      info.AddValue("eq", EqualityComparer);
+      for (int i = 0; i < size; i++)
+            {
+        info.AddValue("elem" + i, array[i + offset]);
+      }
+    }
+*/
+        #endregion
+
+        #region System.Collections.Generic.IList<T> Members
+
+        void System.Collections.Generic.IList<T>.RemoveAt(int index)
+        {
+            RemoveAt(index);
+        }
+
+        void System.Collections.Generic.ICollection<T>.Add(T item)
+        {
+            Add(item);
+        }
+
+        #endregion
+
+        #region System.Collections.ICollection Members
+
+        bool System.Collections.ICollection.IsSynchronized
+        {
+            get { return false; }
+        }
+
+        [Obsolete]
+        Object System.Collections.ICollection.SyncRoot
+        {
+            get { return underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; }
+        }
+
+        void System.Collections.ICollection.CopyTo(Array arr, int index)
+        {
+            if (index < 0 || index + Count > arr.Length)
+                throw new ArgumentOutOfRangeException();
+
+            foreach (T item in this)
+                arr.SetValue(item, index++);
+        }
+
+        #endregion
+
+        #region System.Collections.IList Members
+
+        Object System.Collections.IList.this[int index]
+        {
+            get { return this[index]; }
+            set { this[index] = (T)value; }
+        }
+
+        int System.Collections.IList.Add(Object o)
+        {
+            bool added = Add((T)o);
+            // What position to report if item not added? SC.IList.Add doesn't say
+            return added ? Count - 1 : -1;
+        }
+
+        bool System.Collections.IList.Contains(Object o)
+        {
+            return Contains((T)o);
+        }
+
+        int System.Collections.IList.IndexOf(Object o)
+        {
+            return Math.Max(-1, IndexOf((T)o));
+        }
+
+        void System.Collections.IList.Insert(int index, Object o)
+        {
+            Insert(index, (T)o);
+        }
+
+        void System.Collections.IList.Remove(Object o)
+        {
+            Remove((T)o);
+        }
+
+        void System.Collections.IList.RemoveAt(int index)
+        {
+            RemoveAt(index);
+        }
+
+        #endregion
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/DropMultiplicity.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/DropMultiplicity.cs b/src/Lucene.Net.Tests/core/Support/C5/DropMultiplicity.cs
new file mode 100644
index 0000000..b2c5e9f
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/DropMultiplicity.cs
@@ -0,0 +1,15 @@
+\ufeffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Support.C5
+{
+    [Serializable]
+    class DropMultiplicity<K> : MappedCollectionValue<KeyValuePair<K, int>, K>
+    {
+        public DropMultiplicity(ICollectionValue<KeyValuePair<K, int>> coll) : base(coll) { }
+        public override K Map(KeyValuePair<K, int> kvp) { return kvp.Key; }
+    }
+}


[56/58] [abbrv] lucenenet git commit: Grouping: Renamed _other parameter to other

Posted by ni...@apache.org.
Grouping: Renamed _other parameter to other


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

Branch: refs/heads/grouping
Commit: 987a985456c8aedd53b5aabe21b3488948460a61
Parents: 04f4013
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Mon Nov 7 23:07:09 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:34 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Grouping/SearchGroup.cs | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/987a9854/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index bbf2082..a3ad0d3 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -140,39 +140,39 @@ namespace Lucene.Net.Search.Grouping
             }
 
             // Only for assert
-            private bool NeverEquals(object _other)
+            private bool NeverEquals(object other)
             {
-                if (_other is MergedGroup<T>)
+                if (other is MergedGroup<T>)
                 {
-                    MergedGroup<T> other = (MergedGroup<T>)_other;
+                    MergedGroup<T> otherMergedGroup = (MergedGroup<T>)other;
                     if (groupValue == null)
                     {
-                        Debug.Assert(other.groupValue != null);
+                        Debug.Assert(otherMergedGroup.groupValue != null);
                     }
                     else
                     {
-                        Debug.Assert(!groupValue.Equals(other.groupValue));
+                        Debug.Assert(!groupValue.Equals(otherMergedGroup.groupValue));
                     }
                 }
                 return true;
             }
 
-            public override bool Equals(object _other)
+            public override bool Equals(object other)
             {
                 // We never have another MergedGroup instance with
                 // same groupValue
-                Debug.Assert(NeverEquals(_other));
+                Debug.Assert(NeverEquals(other));
 
-                if (_other is MergedGroup<T>)
+                if (other is MergedGroup<T>)
                 {
-                    MergedGroup<T> other = (MergedGroup<T>)_other;
+                    MergedGroup<T> otherMergedGroup = (MergedGroup<T>)other;
                     if (groupValue == null)
                     {
-                        return other == null;
+                        return otherMergedGroup == null;
                     }
                     else
                     {
-                        return groupValue.Equals(other);
+                        return groupValue.Equals(otherMergedGroup);
                     }
                 }
                 else


[28/58] [abbrv] lucenenet git commit: WIP on Grouping

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
new file mode 100644
index 0000000..cda472d
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -0,0 +1,1692 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Documents;
+using Lucene.Net.Index;
+using Lucene.Net.Queries.Function;
+using Lucene.Net.Queries.Function.ValueSources;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Search.Grouping.Terms;
+using Lucene.Net.Store;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using Lucene.Net.Util.Mutable;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.Search.Grouping
+{
+    // TODO
+    //   - should test relevance sort too
+    //   - test null
+    //   - test ties
+    //   - test compound sort
+    public class TestGrouping : LuceneTestCase
+    {
+        [Test]
+        public void testBasic()
+        {
+
+            string groupField = "author";
+
+            FieldType customType = new FieldType();
+            customType.Stored = (true);
+
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(
+                                       Random(),
+                                       dir,
+                                       NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                                                            new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            // 0
+            Document doc = new Document();
+            addGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "random text", Field.Store.YES));
+            doc.Add(new Field("id", "1", customType));
+            w.AddDocument(doc);
+
+            // 1
+            doc = new Document();
+            addGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "some more random text", Field.Store.YES));
+            doc.Add(new Field("id", "2", customType));
+            w.AddDocument(doc);
+
+            // 2
+            doc = new Document();
+            addGroupField(doc, groupField, "author1", canUseIDV);
+            doc.Add(new TextField("content", "some more random textual data", Field.Store.YES));
+            doc.Add(new Field("id", "3", customType));
+            w.AddDocument(doc);
+
+            // 3
+            doc = new Document();
+            addGroupField(doc, groupField, "author2", canUseIDV);
+            doc.Add(new TextField("content", "some random text", Field.Store.YES));
+            doc.Add(new Field("id", "4", customType));
+            w.AddDocument(doc);
+
+            // 4
+            doc = new Document();
+            addGroupField(doc, groupField, "author3", canUseIDV);
+            doc.Add(new TextField("content", "some more random text", Field.Store.YES));
+            doc.Add(new Field("id", "5", customType));
+            w.AddDocument(doc);
+
+            // 5
+            doc = new Document();
+            addGroupField(doc, groupField, "author3", canUseIDV);
+            doc.Add(new TextField("content", "random", Field.Store.YES));
+            doc.Add(new Field("id", "6", customType));
+            w.AddDocument(doc);
+
+            // 6 -- no author field
+            doc = new Document();
+            doc.Add(new TextField("content", "random word stuck in alot of other text", Field.Store.YES));
+            doc.Add(new Field("id", "6", customType));
+            w.AddDocument(doc);
+
+            IndexSearcher indexSearcher = NewSearcher(w.Reader);
+            w.Dispose();
+
+            Sort groupSort = Sort.RELEVANCE;
+
+            if (canUseIDV && Random().nextBoolean())
+            {
+                groupField += "_dv";
+            }
+
+            AbstractFirstPassGroupingCollector <?> c1 = createRandomFirstPassCollector(groupField, groupSort, 10);
+            indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c1);
+
+            AbstractSecondPassGroupingCollector <?> c2 = createSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, true, true);
+            indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c2);
+
+            TopGroups <?> groups = c2.getTopGroups(0);
+            assertFalse(float.IsNaN(groups.maxScore));
+
+            assertEquals(7, groups.totalHitCount);
+            assertEquals(7, groups.totalGroupedHitCount);
+            assertEquals(4, groups.groups.Length);
+
+            // relevance order: 5, 0, 3, 4, 1, 2, 6
+
+            // the later a document is added the higher this docId
+            // value
+            GroupDocs <?> group = groups.groups[0];
+            compareGroupValue("author3", group);
+            assertEquals(2, group.scoreDocs.Length);
+            assertEquals(5, group.scoreDocs[0].doc);
+            assertEquals(4, group.scoreDocs[1].doc);
+            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
+
+            group = groups.groups[1];
+            compareGroupValue("author1", group);
+            assertEquals(3, group.scoreDocs.Length);
+            assertEquals(0, group.scoreDocs[0].doc);
+            assertEquals(1, group.scoreDocs[1].doc);
+            assertEquals(2, group.scoreDocs[2].doc);
+            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
+            assertTrue(group.scoreDocs[1].score > group.scoreDocs[2].score);
+
+            group = groups.groups[2];
+            compareGroupValue("author2", group);
+            assertEquals(1, group.scoreDocs.Length);
+            assertEquals(3, group.scoreDocs[0].doc);
+
+            group = groups.groups[3];
+            compareGroupValue(null, group);
+            assertEquals(1, group.scoreDocs.Length);
+            assertEquals(6, group.scoreDocs[0].doc);
+
+            indexSearcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        private void addGroupField(Document doc, string groupField, string value, bool canUseIDV)
+        {
+            doc.Add(new TextField(groupField, value, Field.Store.YES));
+            if (canUseIDV)
+            {
+                doc.Add(new SortedDocValuesField(groupField + "_dv", new BytesRef(value)));
+            }
+        }
+
+        private AbstractFirstPassGroupingCollector<?> createRandomFirstPassCollector(String groupField, Sort groupSort, int topDocs)
+        {
+            AbstractFirstPassGroupingCollector <?> selected;
+            if (Random().nextbool())
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                selected = new FunctionFirstPassGroupingCollector(vs, new Dictionary(), groupSort, topDocs);
+            }
+            else
+            {
+                selected = new TermFirstPassGroupingCollector(groupField, groupSort, topDocs);
+            }
+            if (VERBOSE)
+            {
+                Console.WriteLine("Selected implementation: " + selected.GetType().Name);
+            }
+            return selected;
+        }
+
+        private AbstractFirstPassGroupingCollector<?> createFirstPassCollector(string groupField, Sort groupSort, int topDocs, AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector)
+        {
+            if (typeof(TermFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                return new FunctionFirstPassGroupingCollector(vs, new Dictionary(), groupSort, topDocs);
+            }
+            else
+            {
+                return new TermFirstPassGroupingCollector(groupField, groupSort, topDocs);
+            }
+        }
+
+        private <T> AbstractSecondPassGroupingCollector<T> createSecondPassCollector(AbstractFirstPassGroupingCollector firstPassGroupingCollector,
+                                                                              string groupField,
+                                                                              Sort groupSort,
+                                                                              Sort sortWithinGroup,
+                                                                              int groupOffset,
+                                                                              int maxDocsPerGroup,
+                                                                              bool getScores,
+                                                                              bool getMaxScores,
+                                                                              bool fillSortFields)
+        {
+
+            if (typeof(TermFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
+            {
+                ICollection<SearchGroup<BytesRef>> searchGroups = firstPassGroupingCollector.GetTopGroups(groupOffset, fillSortFields);
+                return (AbstractSecondPassGroupingCollector)new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
+            }
+            else
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                ICollection<SearchGroup<MutableValue>> searchGroups = firstPassGroupingCollector.GetTopGroups(groupOffset, fillSortFields);
+                return (AbstractSecondPassGroupingCollector)new FunctionSecondPassGroupingCollector(searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap());
+            }
+        }
+
+        // Basically converts searchGroups from MutableValue to BytesRef if grouping by ValueSource
+        private AbstractSecondPassGroupingCollector<?> createSecondPassCollector(AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector,
+                                                                              string groupField,
+                                                                              ICollection<SearchGroup<BytesRef>> searchGroups,
+                                                                              Sort groupSort,
+                                                                              Sort sortWithinGroup,
+                                                                              int maxDocsPerGroup,
+                                                                              bool getScores,
+                                                                              bool getMaxScores,
+                                                                              bool fillSortFields)
+        {
+            if (firstPassGroupingCollector.GetType().IsAssignableFrom(typeof(TermFirstPassGroupingCollector)))
+            {
+                return new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
+            }
+            else
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                List<SearchGroup<MutableValue>> mvalSearchGroups = new List<SearchGroup<MutableValue>>(searchGroups.size());
+                foreach (SearchGroup<BytesRef> mergedTopGroup in searchGroups)
+                {
+                    SearchGroup<MutableValue> sg = new SearchGroup<MutableValue>();
+                    MutableValueStr groupValue = new MutableValueStr();
+                    if (mergedTopGroup.groupValue != null)
+                    {
+                        groupValue.Value = mergedTopGroup.groupValue;
+                    }
+                    else
+                    {
+                        groupValue.Value = new BytesRef();
+                        groupValue.Exists = false;
+                    }
+                    sg.groupValue = groupValue;
+                    sg.sortValues = mergedTopGroup.sortValues;
+                    mvalSearchGroups.Add(sg);
+                }
+
+                return new FunctionSecondPassGroupingCollector(mvalSearchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap<>());
+            }
+        }
+
+        private AbstractAllGroupsCollector<?> createAllGroupsCollector(AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector,
+                                                                    string groupField)
+        {
+            if (firstPassGroupingCollector.GetType().IsAssignableFrom(typeof(TermFirstPassGroupingCollector)))
+            {
+                return new TermAllGroupsCollector(groupField);
+            }
+            else
+            {
+                ValueSource vs = new BytesRefFieldSource(groupField);
+                return new FunctionAllGroupsCollector(vs, new HashMap<>());
+            }
+        }
+
+        private void compareGroupValue<T>(string expected, GroupDocs<T> group)
+        {
+            if (expected == null)
+            {
+                if (group.GroupValue == null)
+                {
+                    return;
+                }
+                else if (group.GroupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
+                {
+                    return;
+                }
+                else if ((group.GroupValue as BytesRef).Length == 0)
+                {
+                    return;
+                }
+                fail();
+            }
+
+            if (group.GroupValue.GetType().IsAssignableFrom(typeof(BytesRef)))
+            {
+                assertEquals(new BytesRef(expected), group.GroupValue);
+            }
+            else if (group.GroupValue.GetType().IsAssignableFrom(typeof(MutableValueStr)))
+            {
+                MutableValueStr v = new MutableValueStr();
+                v.Value = new BytesRef(expected);
+                assertEquals(v, group.GroupValue);
+            }
+            else
+            {
+                fail();
+            }
+        }
+
+        private ICollection<SearchGroup<BytesRef>> getSearchGroups<T>(AbstractFirstPassGroupingCollector<T> c, int groupOffset, bool fillFields)
+        {
+            if (typeof(TermFirstPassGroupingCollector).IsAssignableFrom(c.GetType()))
+            {
+
+                return (ICollection<SearchGroup<BytesRef>>)c.GetTopGroups(groupOffset, fillFields);
+            }
+            else if (typeof(FunctionFirstPassGroupingCollector).IsAssignableFrom(c.GetType()))
+            {
+                var mutableValueGroups = c.GetTopGroups(groupOffset, fillFields);
+                if (mutableValueGroups == null)
+                {
+                    return null;
+                }
+
+                List<SearchGroup<BytesRef>> groups = new List<SearchGroup<BytesRef>>(mutableValueGroups.size());
+                foreach (var mutableValueGroup in mutableValueGroups)
+                {
+                    SearchGroup<BytesRef> sg = new SearchGroup<BytesRef>();
+                    sg.groupValue = mutableValueGroup.groupValue.Exists ? ((MutableValueStr)mutableValueGroup.groupValue).Value : null;
+                    sg.sortValues = mutableValueGroup.sortValues;
+                    groups.Add(sg);
+                }
+                return groups;
+            }
+            fail();
+            return null;
+        }
+
+        private TopGroups<BytesRef> getTopGroups<T>(AbstractSecondPassGroupingCollector<T> c, int withinGroupOffset)
+        {
+            if (c.GetType().IsAssignableFrom(typeof(TermSecondPassGroupingCollector)))
+            {
+                return ((TermSecondPassGroupingCollector)c).GetTopGroups(withinGroupOffset);
+            }
+            else if (c.GetType().IsAssignableFrom(typeof(FunctionSecondPassGroupingCollector)))
+            {
+                TopGroups<MutableValue> mvalTopGroups = ((FunctionSecondPassGroupingCollector)c).GetTopGroups(withinGroupOffset);
+                List<GroupDocs<BytesRef>> groups = new List<GroupDocs<BytesRef>>(mvalTopGroups.Groups.Length);
+                foreach (GroupDocs<MutableValue> mvalGd in mvalTopGroups.Groups)
+                {
+                    BytesRef groupValue = mvalGd.GroupValue.Exists ? ((MutableValueStr)mvalGd.GroupValue).Value : null;
+                    groups.Add(new GroupDocs<BytesRef>(float.NaN, mvalGd.MaxScore, mvalGd.TotalHits, mvalGd.ScoreDocs, groupValue, mvalGd.GroupSortValues));
+                }
+                return new TopGroups<BytesRef>(mvalTopGroups.GroupSort, mvalTopGroups.WithinGroupSort, mvalTopGroups.TotalHitCount, mvalTopGroups.TotalGroupedHitCount, groups.ToArray(/*new GroupDocs[groups.size()]*/), float.NaN);
+            }
+            fail();
+            return null;
+        }
+
+        internal class GroupDoc
+        {
+            internal readonly int id;
+            internal readonly BytesRef group;
+            internal readonly BytesRef sort1;
+            internal readonly BytesRef sort2;
+            // content must be "realN ..."
+            internal readonly string content;
+            internal float score;
+            internal float score2;
+
+            public GroupDoc(int id, BytesRef group, BytesRef sort1, BytesRef sort2, string content)
+            {
+                this.id = id;
+                this.group = group;
+                this.sort1 = sort1;
+                this.sort2 = sort2;
+                this.content = content;
+            }
+        }
+
+        private Sort getRandomSort()
+        {
+            List<SortField> sortFields = new List<SortField>();
+            if (Random().nextInt(7) == 2)
+            {
+                sortFields.Add(SortField.FIELD_SCORE);
+            }
+            else
+            {
+                if (Random().nextBoolean())
+                {
+                    if (Random().nextBoolean())
+                    {
+                        sortFields.Add(new SortField("sort1", SortField.Type_e.STRING, Random().nextBoolean()));
+                    }
+                    else
+                    {
+                        sortFields.Add(new SortField("sort2", SortField.Type_e.STRING, Random().nextBoolean()));
+                    }
+                }
+                else if (Random().nextBoolean())
+                {
+                    sortFields.Add(new SortField("sort1", SortField.Type_e.STRING, Random().nextBoolean()));
+                    sortFields.Add(new SortField("sort2", SortField.Type_e.STRING, Random().nextBoolean()));
+                }
+            }
+            // Break ties:
+            sortFields.Add(new SortField("id", SortField.Type_e.INT));
+            return new Sort(sortFields.ToArray(/*new SortField[sortFields.size()]*/));
+        }
+
+        internal class ComparerAnonymousHelper : IComparer<GroupDoc>
+        {
+            private readonly TestGrouping outerInstance;
+            private readonly SortField[] sortFields;
+            internal ComparerAnonymousHelper(TestGrouping outerInstance, SortField[] sortFields)
+            {
+                this.outerInstance = outerInstance;
+                this.sortFields = sortFields;
+            }
+
+            public int Compare(GroupDoc d1, GroupDoc d2)
+            {
+                foreach (SortField sf in sortFields)
+                {
+                    int cmp;
+                    if (sf.Type == SortField.Type_e.SCORE)
+                    {
+                        if (d1.score > d2.score)
+                        {
+                            cmp = -1;
+                        }
+                        else if (d1.score < d2.score)
+                        {
+                            cmp = 1;
+                        }
+                        else
+                        {
+                            cmp = 0;
+                        }
+                    }
+                    else if (sf.Field.equals("sort1"))
+                    {
+                        cmp = d1.sort1.CompareTo(d2.sort1);
+                    }
+                    else if (sf.Field.equals("sort2"))
+                    {
+                        cmp = d1.sort2.CompareTo(d2.sort2);
+                    }
+                    else
+                    {
+                        assertEquals(sf.Field, "id");
+                        cmp = d1.id - d2.id;
+                    }
+                    if (cmp != 0)
+                    {
+                        return sf.Reverse ? -cmp : cmp;
+                    }
+                }
+                // Our sort always fully tie breaks:
+                fail();
+                return 0;
+            }
+        }
+
+        private IComparer<GroupDoc> getComparator(Sort sort)
+        {
+            SortField[] sortFields = sort.GetSort();
+            return new ComparerAnonymousHelper(this, sortFields);
+            //    return new Comparator<GroupDoc>() {
+            //      @Override
+            //      public int compare(GroupDoc d1, GroupDoc d2)
+            //{
+            //    for (SortField sf : sortFields)
+            //    {
+            //        final int cmp;
+            //        if (sf.getType() == SortField.Type.SCORE)
+            //        {
+            //            if (d1.score > d2.score)
+            //            {
+            //                cmp = -1;
+            //            }
+            //            else if (d1.score < d2.score)
+            //            {
+            //                cmp = 1;
+            //            }
+            //            else
+            //            {
+            //                cmp = 0;
+            //            }
+            //        }
+            //        else if (sf.getField().equals("sort1"))
+            //        {
+            //            cmp = d1.sort1.compareTo(d2.sort1);
+            //        }
+            //        else if (sf.getField().equals("sort2"))
+            //        {
+            //            cmp = d1.sort2.compareTo(d2.sort2);
+            //        }
+            //        else
+            //        {
+            //            assertEquals(sf.getField(), "id");
+            //            cmp = d1.id - d2.id;
+            //        }
+            //        if (cmp != 0)
+            //        {
+            //            return sf.getReverse() ? -cmp : cmp;
+            //        }
+            //    }
+            //    // Our sort always fully tie breaks:
+            //    fail();
+            //    return 0;
+            //}
+            //    };
+        }
+
+        private IComparable[] FillFields(GroupDoc d, Sort sort)
+        {
+            SortField[] sortFields = sort.GetSort();
+            IComparable[] fields = new IComparable[sortFields.Length];
+            for (int fieldIDX = 0; fieldIDX < sortFields.Length; fieldIDX++)
+            {
+                IComparable c;
+                SortField sf = sortFields[fieldIDX];
+                if (sf.Type == SortField.Type_e.SCORE)
+                {
+                    c = new float?(d.score);
+                }
+                else if (sf.Field.equals("sort1"))
+                {
+                    c = d.sort1;
+                }
+                else if (sf.Field.equals("sort2"))
+                {
+                    c = d.sort2;
+                }
+                else
+                {
+                    assertEquals("id", sf.Field);
+                    c = new int?(d.id);
+                }
+                fields[fieldIDX] = c;
+            }
+            return fields;
+        }
+
+        private string groupToString(BytesRef b)
+        {
+            if (b == null)
+            {
+                return "null";
+            }
+            else
+            {
+                return b.Utf8ToString();
+            }
+        }
+
+        private TopGroups<BytesRef> slowGrouping(GroupDoc[] groupDocs,
+                                                 string searchTerm,
+                                                 bool fillFields,
+                                                 bool getScores,
+                                                 bool getMaxScores,
+                                                 bool doAllGroups,
+                                                 Sort groupSort,
+                                                 Sort docSort,
+                                                 int topNGroups,
+                                                 int docsPerGroup,
+                                                 int groupOffset,
+                                                 int docOffset)
+        {
+
+            IComparer<GroupDoc> groupSortComp = getComparator(groupSort);
+
+            Array.Sort(groupDocs, groupSortComp);
+            HashMap<BytesRef, List<GroupDoc>> groups = new HashMap<BytesRef, List<GroupDoc>>();
+            List<BytesRef> sortedGroups = new List<BytesRef>();
+            List<IComparable[]> sortedGroupFields = new List<IComparable[]>();
+
+            int totalHitCount = 0;
+            ISet<BytesRef> knownGroups = new HashSet<BytesRef>();
+
+            //Console.WriteLine("TEST: slowGrouping");
+            foreach (GroupDoc d in groupDocs)
+            {
+                // TODO: would be better to filter by searchTerm before sorting!
+                if (!d.content.StartsWith(searchTerm))
+                {
+                    continue;
+                }
+                totalHitCount++;
+                //Console.WriteLine("  match id=" + d.id + " score=" + d.score);
+
+                if (doAllGroups)
+                {
+                    if (!knownGroups.contains(d.group))
+                    {
+                        knownGroups.add(d.group);
+                        //Console.WriteLine("    add group=" + groupToString(d.group));
+                    }
+                }
+
+                List<GroupDoc> l = groups[d.group];
+                if (l == null)
+                {
+                    //Console.WriteLine("    add sortedGroup=" + groupToString(d.group));
+                    sortedGroups.Add(d.group);
+                    if (fillFields)
+                    {
+                        sortedGroupFields.Add(FillFields(d, groupSort));
+                    }
+                    l = new List<GroupDoc>();
+                    groups.Put(d.group, l);
+                }
+                l.Add(d);
+            }
+
+            if (groupOffset >= sortedGroups.size())
+            {
+                // slice is out of bounds
+                return null;
+            }
+
+            int limit = Math.Min(groupOffset + topNGroups, groups.size());
+
+            IComparer<GroupDoc> docSortComp = getComparator(docSort);
+
+            GroupDocs<BytesRef>[] result = new GroupDocs<BytesRef>[limit - groupOffset];
+            int totalGroupedHitCount = 0;
+            for (int idx = groupOffset; idx < limit; idx++)
+            {
+                BytesRef group = sortedGroups[idx];
+                List<GroupDoc> docs = groups[group];
+                totalGroupedHitCount += docs.size();
+                //Collections.sort(docs, docSortComp);
+                docs.Sort(docSortComp);
+                ScoreDoc[] hits;
+                if (docs.size() > docOffset)
+                {
+                    int docIDXLimit = Math.Min(docOffset + docsPerGroup, docs.size());
+                    hits = new ScoreDoc[docIDXLimit - docOffset];
+                    for (int docIDX = docOffset; docIDX < docIDXLimit; docIDX++)
+                    {
+                        GroupDoc d = docs[docIDX];
+                        FieldDoc fd;
+                        if (fillFields)
+                        {
+                            fd = new FieldDoc(d.id, getScores ? d.score : float.NaN, FillFields(d, docSort));
+                        }
+                        else
+                        {
+                            fd = new FieldDoc(d.id, getScores ? d.score : float.NaN);
+                        }
+                        hits[docIDX - docOffset] = fd;
+                    }
+                }
+                else
+                {
+                    hits = new ScoreDoc[0];
+                }
+
+                result[idx - groupOffset] = new GroupDocs<BytesRef>(float.NaN,
+                                                                  0.0f,
+                                                                  docs.size(),
+                                                                  hits,
+                                                                  group,
+                                                                  fillFields ? sortedGroupFields[idx] : null);
+            }
+
+            if (doAllGroups)
+            {
+                return new TopGroups<BytesRef>(
+                                               new TopGroups<BytesRef>(groupSort.GetSort(), docSort.GetSort(), totalHitCount, totalGroupedHitCount, result, float.NaN),
+                                               knownGroups.size()
+                );
+            }
+            else
+            {
+                return new TopGroups<BytesRef>(groupSort.GetSort(), docSort.GetSort(), totalHitCount, totalGroupedHitCount, result, float.NaN);
+            }
+        }
+
+        private DirectoryReader getDocBlockReader(Directory dir, GroupDoc[] groupDocs)
+        {
+            // Coalesce by group, but in random order:
+            //Collections.shuffle(Arrays.asList(groupDocs), Random());
+            groupDocs = CollectionsHelper.Shuffle(Arrays.AsList(groupDocs)).ToArray();
+            HashMap<BytesRef, List<GroupDoc>> groupMap = new HashMap<BytesRef, List<GroupDoc>>();
+            List<BytesRef> groupValues = new List<BytesRef>();
+
+            foreach (GroupDoc groupDoc in groupDocs)
+            {
+                if (!groupMap.ContainsKey(groupDoc.group))
+                {
+                    groupValues.Add(groupDoc.group);
+                    groupMap.Put(groupDoc.group, new List<GroupDoc>());
+                }
+                groupMap[groupDoc.group].Add(groupDoc);
+            }
+
+            RandomIndexWriter w = new RandomIndexWriter(
+                                                        Random(),
+                                                        dir,
+                                                        NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                                                                             new MockAnalyzer(Random())));
+
+            List<List<Document>> updateDocs = new List<List<Document>>();
+
+            FieldType groupEndType = new FieldType(StringField.TYPE_NOT_STORED);
+            groupEndType.IndexOptions = (FieldInfo.IndexOptions.DOCS_ONLY);
+            groupEndType.OmitNorms = (true);
+
+            //Console.WriteLine("TEST: index groups");
+            foreach (BytesRef group in groupValues)
+            {
+                List<Document> docs = new List<Document>();
+                //Console.WriteLine("TEST:   group=" + (group == null ? "null" : group.utf8ToString()));
+                foreach (GroupDoc groupValue in groupMap[group])
+                {
+                    Document doc = new Document();
+                    docs.Add(doc);
+                    if (groupValue.group != null)
+                    {
+                        doc.Add(NewStringField("group", groupValue.group.Utf8ToString(), Field.Store.NO));
+                    }
+                    doc.Add(NewStringField("sort1", groupValue.sort1.Utf8ToString(), Field.Store.NO));
+                    doc.Add(NewStringField("sort2", groupValue.sort2.Utf8ToString(), Field.Store.NO));
+                    doc.Add(new IntField("id", groupValue.id, Field.Store.NO));
+                    doc.Add(NewTextField("content", groupValue.content, Field.Store.NO));
+                    //Console.WriteLine("TEST:     doc content=" + groupValue.content + " group=" + (groupValue.group == null ? "null" : groupValue.group.utf8ToString()) + " sort1=" + groupValue.sort1.utf8ToString() + " id=" + groupValue.id);
+                }
+                // So we can pull filter marking last doc in block:
+                Field groupEnd = NewField("groupend", "x", groupEndType);
+                docs[docs.size() - 1].Add(groupEnd);
+                // Add as a doc block:
+                w.AddDocuments(docs);
+                if (group != null && Random().nextInt(7) == 4)
+                {
+                    updateDocs.Add(docs);
+                }
+            }
+
+            foreach (List<Document> docs in updateDocs)
+            {
+                // Just replaces docs w/ same docs:
+                w.UpdateDocuments(new Index.Term("group", docs[0].Get("group")), docs);
+            }
+
+            DirectoryReader r = w.Reader;
+            w.Dispose();
+
+            return r;
+        }
+
+        internal class ShardState
+        {
+
+            public readonly ShardSearcher[] subSearchers;
+            public readonly int[] docStarts;
+
+            public ShardState(IndexSearcher s)
+            {
+                IndexReaderContext ctx = s.TopReaderContext;
+                IList<AtomicReaderContext> leaves = ctx.Leaves;
+                subSearchers = new ShardSearcher[leaves.size()];
+                for (int searcherIDX = 0; searcherIDX < subSearchers.Length; searcherIDX++)
+                {
+                    subSearchers[searcherIDX] = new ShardSearcher(leaves[searcherIDX], ctx);
+                }
+
+                docStarts = new int[subSearchers.Length];
+                for (int subIDX = 0; subIDX < docStarts.Length; subIDX++)
+                {
+                    docStarts[subIDX] = leaves[subIDX].DocBase;
+                    //Console.WriteLine("docStarts[" + subIDX + "]=" + docStarts[subIDX]);
+                }
+            }
+        }
+
+        [Test]
+        public void testRandom()
+        {
+            int numberOfRuns = TestUtil.NextInt(Random(), 3, 6);
+            for (int iter = 0; iter < numberOfRuns; iter++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: iter=" + iter);
+                }
+
+                int numDocs = TestUtil.NextInt(Random(), 100, 1000) * RANDOM_MULTIPLIER;
+                //final int numDocs = TestUtil.nextInt(random, 5, 20);
+
+                int numGroups = TestUtil.NextInt(Random(), 1, numDocs);
+
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: numDocs=" + numDocs + " numGroups=" + numGroups);
+                }
+
+                List<BytesRef> groups = new List<BytesRef>();
+                for (int i = 0; i < numGroups; i++)
+                {
+                    string randomValue;
+                    do
+                    {
+                        // B/c of DV based impl we can't see the difference between an empty string and a null value.
+                        // For that reason we don't generate empty string
+                        // groups.
+                        randomValue = TestUtil.RandomRealisticUnicodeString(Random());
+                        //randomValue = TestUtil.randomSimpleString(Random());
+                    } while ("".equals(randomValue));
+
+                    groups.Add(new BytesRef(randomValue));
+                }
+                string[] contentStrings = new string[TestUtil.NextInt(Random(), 2, 20)];
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: create fake content");
+                }
+                for (int contentIDX = 0; contentIDX < contentStrings.Length; contentIDX++)
+                {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("real").append(Random().nextInt(3)).append(' ');
+                    int fakeCount = Random().nextInt(10);
+                    for (int fakeIDX = 0; fakeIDX < fakeCount; fakeIDX++)
+                    {
+                        sb.append("fake ");
+                    }
+                    contentStrings[contentIDX] = sb.toString();
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  content=" + sb.toString());
+                    }
+                }
+
+                Directory dir = NewDirectory();
+                RandomIndexWriter w = new RandomIndexWriter(
+                                                            Random(),
+                                                            dir,
+                                                            NewIndexWriterConfig(TEST_VERSION_CURRENT,
+                                                                                 new MockAnalyzer(Random())));
+                bool preFlex = "Lucene3x".equals(w.w.Config.Codec.Name);
+                bool canUseIDV = !preFlex;
+
+                Document doc = new Document();
+                Document docNoGroup = new Document();
+                Field idvGroupField = new SortedDocValuesField("group_dv", new BytesRef());
+                if (canUseIDV)
+                {
+                    doc.Add(idvGroupField);
+                    docNoGroup.Add(idvGroupField);
+                }
+
+                Field group = NewStringField("group", "", Field.Store.NO);
+                doc.Add(group);
+                Field sort1 = NewStringField("sort1", "", Field.Store.NO);
+                doc.Add(sort1);
+                docNoGroup.Add(sort1);
+                Field sort2 = NewStringField("sort2", "", Field.Store.NO);
+                doc.Add(sort2);
+                docNoGroup.Add(sort2);
+                Field content = NewTextField("content", "", Field.Store.NO);
+                doc.Add(content);
+                docNoGroup.Add(content);
+                IntField id = new IntField("id", 0, Field.Store.NO);
+                doc.Add(id);
+                docNoGroup.Add(id);
+                GroupDoc[] groupDocs = new GroupDoc[numDocs];
+                for (int i = 0; i < numDocs; i++)
+                {
+                    BytesRef groupValue;
+                    if (Random().nextInt(24) == 17)
+                    {
+                        // So we test the "doc doesn't have the group'd
+                        // field" case:
+                        groupValue = null;
+                    }
+                    else
+                    {
+                        groupValue = groups[Random().nextInt(groups.size())];
+                    }
+                    GroupDoc groupDoc = new GroupDoc(i,
+                                                           groupValue,
+                                                           groups[Random().nextInt(groups.size())],
+                                                           groups[Random().nextInt(groups.size())],
+                                                           contentStrings[Random().nextInt(contentStrings.Length)]);
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  doc content=" + groupDoc.content + " id=" + i + " group=" + (groupDoc.group == null ? "null" : groupDoc.group.Utf8ToString()) + " sort1=" + groupDoc.sort1.Utf8ToString() + " sort2=" + groupDoc.sort2.Utf8ToString());
+                    }
+
+                    groupDocs[i] = groupDoc;
+                    if (groupDoc.group != null)
+                    {
+                        group.StringValue = (groupDoc.group.Utf8ToString());
+                        if (canUseIDV)
+                        {
+                            idvGroupField.BytesValue = (BytesRef.DeepCopyOf(groupDoc.group));
+                        }
+                    }
+                    else if (canUseIDV)
+                    {
+                        // Must explicitly set empty string, else eg if
+                        // the segment has all docs missing the field then
+                        // we get null back instead of empty BytesRef:
+                        idvGroupField.BytesValue = (new BytesRef());
+                    }
+                    sort1.StringValue = (groupDoc.sort1.Utf8ToString());
+                    sort2.StringValue = (groupDoc.sort2.Utf8ToString());
+                    content.StringValue = (groupDoc.content);
+                    id.IntValue = (groupDoc.id);
+                    if (groupDoc.group == null)
+                    {
+                        w.AddDocument(docNoGroup);
+                    }
+                    else
+                    {
+                        w.AddDocument(doc);
+                    }
+                }
+
+                GroupDoc[] groupDocsByID = new GroupDoc[groupDocs.Length];
+                System.Array.Copy(groupDocs, 0, groupDocsByID, 0, groupDocs.Length);
+
+                DirectoryReader r = w.Reader;
+                w.Dispose();
+
+                // NOTE: intentional but temporary field cache insanity!
+                FieldCache.Ints docIDToID = FieldCache.DEFAULT.GetInts(SlowCompositeReaderWrapper.Wrap(r), "id", false);
+                DirectoryReader rBlocks = null;
+                Directory dirBlocks = null;
+
+                try
+                {
+                    IndexSearcher s = NewSearcher(r);
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("\nTEST: searcher=" + s);
+                    }
+
+                    if (typeof(SlowCompositeReaderWrapper).IsAssignableFrom(s.IndexReader.GetType()))
+                    {
+                        canUseIDV = false;
+                    }
+                    else
+                    {
+                        canUseIDV = !preFlex;
+                    }
+                    ShardState shards = new ShardState(s);
+
+                    for (int contentID = 0; contentID < 3; contentID++)
+                    {
+                        ScoreDoc[] hits = s.Search(new TermQuery(new Index.Term("content", "real" + contentID)), numDocs).ScoreDocs;
+                        foreach (ScoreDoc hit in hits)
+                        {
+                            GroupDoc gd = groupDocs[docIDToID.Get(hit.Doc)];
+                            assertTrue(gd.score == 0.0);
+                            gd.score = hit.Score;
+                            assertEquals(gd.id, docIDToID.Get(hit.Doc));
+                        }
+                    }
+
+                    foreach (GroupDoc gd in groupDocs)
+                    {
+                        assertTrue(gd.score != 0.0);
+                    }
+
+                    // Build 2nd index, where docs are added in blocks by
+                    // group, so we can use single pass collector
+                    dirBlocks = NewDirectory();
+                    rBlocks = getDocBlockReader(dirBlocks, groupDocs);
+                    Filter lastDocInBlock = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Term("groupend", "x"))));
+                    FieldCache.Ints docIDToIDBlocks = FieldCache.DEFAULT.GetInts(SlowCompositeReaderWrapper.Wrap(rBlocks), "id", false);
+
+                    IndexSearcher sBlocks = NewSearcher(rBlocks);
+                    ShardState shardsBlocks = new ShardState(sBlocks);
+
+                    // ReaderBlocks only increases maxDoc() vs reader, which
+                    // means a monotonic shift in scores, so we can
+                    // reliably remap them w/ Map:
+                    IDictionary<string, IDictionary<float, float>> scoreMap = new Dictionary<string, IDictionary<float, float>>();
+
+                    // Tricky: must separately set .score2, because the doc
+                    // block index was created with possible deletions!
+                    //Console.WriteLine("fixup score2");
+                    for (int contentID = 0; contentID < 3; contentID++)
+                    {
+                        //Console.WriteLine("  term=real" + contentID);
+                        IDictionary<float, float> termScoreMap = new Dictionary<float, float>();
+                        scoreMap.Put("real" + contentID, termScoreMap);
+                        //Console.WriteLine("term=real" + contentID + " dfold=" + s.docFreq(new Term("content", "real"+contentID)) +
+                        //" dfnew=" + sBlocks.docFreq(new Term("content", "real"+contentID)));
+                        ScoreDoc[] hits = sBlocks.Search(new TermQuery(new Term("content", "real" + contentID)), numDocs).ScoreDocs;
+                        foreach (ScoreDoc hit in hits)
+                        {
+                            GroupDoc gd = groupDocsByID[docIDToIDBlocks.Get(hit.Doc)];
+                            assertTrue(gd.score2 == 0.0);
+                            gd.score2 = hit.Score;
+                            assertEquals(gd.id, docIDToIDBlocks.Get(hit.Doc));
+                            //Console.WriteLine("    score=" + gd.score + " score2=" + hit.score + " id=" + docIDToIDBlocks.get(hit.doc));
+                            termScoreMap.Put(gd.score, gd.score2);
+                        }
+                    }
+
+                    for (int searchIter = 0; searchIter < 100; searchIter++)
+                    {
+
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("\nTEST: searchIter=" + searchIter);
+                        }
+
+                        string searchTerm = "real" + Random().nextInt(3);
+                        bool fillFields = Random().nextBoolean();
+                        bool getScores = Random().nextBoolean();
+                        bool getMaxScores = Random().nextBoolean();
+                        Sort groupSort = getRandomSort();
+                        //final Sort groupSort = new Sort(new SortField[] {new SortField("sort1", SortField.STRING), new SortField("id", SortField.INT)});
+                        // TODO: also test null (= sort by relevance)
+                        Sort docSort = getRandomSort();
+
+                        foreach (SortField sf in docSort.GetSort())
+                        {
+                            if (sf.Type == SortField.Type_e.SCORE)
+                            {
+                                getScores = true;
+                                break;
+                            }
+                        }
+
+                        foreach (SortField sf in groupSort.GetSort())
+                        {
+                            if (sf.Type == SortField.Type_e.SCORE)
+                            {
+                                getScores = true;
+                                break;
+                            }
+                        }
+
+                        int topNGroups = TestUtil.NextInt(Random(), 1, 30);
+                        // int topNGroups = 10;
+                        int docsPerGroup = TestUtil.NextInt(Random(), 1, 50);
+
+                        int groupOffset = TestUtil.NextInt(Random(), 0, (topNGroups - 1) / 2);
+                        // int groupOffset = 0;
+
+                        int docOffset = TestUtil.NextInt(Random(), 0, docsPerGroup - 1);
+                        // int docOffset = 0;
+
+                        bool doCache = Random().nextBoolean();
+                        bool doAllGroups = Random().nextBoolean();
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TEST: groupSort=" + groupSort + " docSort=" + docSort + " searchTerm=" + searchTerm + " dF=" + r.DocFreq(new Term("content", searchTerm)) + " dFBlock=" + rBlocks.DocFreq(new Term("content", searchTerm)) + " topNGroups=" + topNGroups + " groupOffset=" + groupOffset + " docOffset=" + docOffset + " doCache=" + doCache + " docsPerGroup=" + docsPerGroup + " doAllGroups=" + doAllGroups + " getScores=" + getScores + " getMaxScores=" + getMaxScores);
+                        }
+
+                        string groupField = "group";
+                        if (canUseIDV && Random().nextBoolean())
+                        {
+                            groupField += "_dv";
+                        }
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("  groupField=" + groupField);
+                        }
+                        AbstractFirstPassGroupingCollector <?> c1 = createRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
+                        CachingCollector cCache;
+                        Collector c;
+
+                        AbstractAllGroupsCollector <?> allGroupsCollector;
+                        if (doAllGroups)
+                        {
+                            allGroupsCollector = createAllGroupsCollector(c1, groupField);
+                        }
+                        else
+                        {
+                            allGroupsCollector = null;
+                        }
+
+                        bool useWrappingCollector = Random().nextBoolean();
+
+                        if (doCache)
+                        {
+                            double maxCacheMB = Random().NextDouble();
+                            if (VERBOSE)
+                            {
+                                Console.WriteLine("TEST: maxCacheMB=" + maxCacheMB);
+                            }
+
+                            if (useWrappingCollector)
+                            {
+                                if (doAllGroups)
+                                {
+                                    cCache = CachingCollector.Create(c1, true, maxCacheMB);
+                                    c = MultiCollector.Wrap(cCache, allGroupsCollector);
+                                }
+                                else
+                                {
+                                    c = cCache = CachingCollector.Create(c1, true, maxCacheMB);
+                                }
+                            }
+                            else
+                            {
+                                // Collect only into cache, then replay multiple times:
+                                c = cCache = CachingCollector.Create(false, true, maxCacheMB);
+                            }
+                        }
+                        else
+                        {
+                            cCache = null;
+                            if (doAllGroups)
+                            {
+                                c = MultiCollector.Wrap(c1, allGroupsCollector);
+                            }
+                            else
+                            {
+                                c = c1;
+                            }
+                        }
+
+                        // Search top reader:
+                        Query query = new TermQuery(new Term("content", searchTerm));
+
+                        s.Search(query, c);
+
+                        if (doCache && !useWrappingCollector)
+                        {
+                            if (cCache.Cached)
+                            {
+                                // Replay for first-pass grouping
+                                cCache.Replay(c1);
+                                if (doAllGroups)
+                                {
+                                    // Replay for all groups:
+                                    cCache.Replay(allGroupsCollector);
+                                }
+                            }
+                            else
+                            {
+                                // Replay by re-running search:
+                                s.Search(query, c1);
+                                if (doAllGroups)
+                                {
+                                    s.Search(query, allGroupsCollector);
+                                }
+                            }
+                        }
+
+                        // Get 1st pass top groups
+                        ICollection<SearchGroup<BytesRef>> topGroups = getSearchGroups(c1, groupOffset, fillFields);
+                        TopGroups<BytesRef> groupsResult;
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TEST: first pass topGroups");
+                            if (topGroups == null)
+                            {
+                                Console.WriteLine("  null");
+                            }
+                            else
+                            {
+                                foreach (SearchGroup<BytesRef> searchGroup in topGroups)
+                                {
+                                    Console.WriteLine("  " + (searchGroup.groupValue == null ? "null" : searchGroup.groupValue.Utf8ToString()) + ": " + Arrays.ToString(searchGroup.sortValues));
+                                }
+                            }
+                        }
+
+                        // Get 1st pass top groups using shards
+
+                        ValueHolder<bool> idvBasedImplsUsedSharded = new ValueHolder<bool>(false);
+                        TopGroups<BytesRef> topGroupsShards = searchShards(s, shards.subSearchers, query, groupSort, docSort,
+                           groupOffset, topNGroups, docOffset, docsPerGroup, getScores, getMaxScores, canUseIDV, preFlex, idvBasedImplsUsedSharded);
+                        AbstractSecondPassGroupingCollector <?> c2;
+                        if (topGroups != null)
+                        {
+
+                            if (VERBOSE)
+                            {
+                                Console.WriteLine("TEST: topGroups");
+                                foreach (SearchGroup<BytesRef> searchGroup in topGroups)
+                                {
+                                    Console.WriteLine("  " + (searchGroup.groupValue == null ? "null" : searchGroup.groupValue.Utf8ToString()) + ": " + Arrays.ToString(searchGroup.sortValues));
+                                }
+                            }
+
+                            c2 = createSecondPassCollector(c1, groupField, groupSort, docSort, groupOffset, docOffset + docsPerGroup, getScores, getMaxScores, fillFields);
+                            if (doCache)
+                            {
+                                if (cCache.Cached)
+                                {
+                                    if (VERBOSE)
+                                    {
+                                        Console.WriteLine("TEST: cache is intact");
+                                    }
+                                    cCache.Replay(c2);
+                                }
+                                else
+                                {
+                                    if (VERBOSE)
+                                    {
+                                        Console.WriteLine("TEST: cache was too large");
+                                    }
+                                    s.Search(query, c2);
+                                }
+                            }
+                            else
+                            {
+                                s.Search(query, c2);
+                            }
+
+                            if (doAllGroups)
+                            {
+                                TopGroups<BytesRef> tempTopGroups = getTopGroups(c2, docOffset);
+                                groupsResult = new TopGroups<BytesRef>(tempTopGroups, allGroupsCollector.getGroupCount());
+                            }
+                            else
+                            {
+                                groupsResult = getTopGroups(c2, docOffset);
+                            }
+                        }
+                        else
+                        {
+                            c2 = null;
+                            groupsResult = null;
+                            if (VERBOSE)
+                            {
+                                Console.WriteLine("TEST:   no results");
+                            }
+                        }
+
+                        TopGroups<BytesRef> expectedGroups = slowGrouping(groupDocs, searchTerm, fillFields, getScores, getMaxScores, doAllGroups, groupSort, docSort, topNGroups, docsPerGroup, groupOffset, docOffset);
+
+                        if (VERBOSE)
+                        {
+                            if (expectedGroups == null)
+                            {
+                                Console.WriteLine("TEST: no expected groups");
+                            }
+                            else
+                            {
+                                Console.WriteLine("TEST: expected groups totalGroupedHitCount=" + expectedGroups.TotalGroupedHitCount);
+                                foreach (GroupDocs<BytesRef> gd in expectedGroups.Groups)
+                                {
+                                    Console.WriteLine("  group=" + (gd.GroupValue == null ? "null" : gd.GroupValue.Utf8ToString()) + " totalHits=" + gd.TotalHits + " scoreDocs.len=" + gd.ScoreDocs.Length);
+                                    foreach (ScoreDoc sd in gd.ScoreDocs)
+                                    {
+                                        Console.WriteLine("    id=" + sd.Doc + " score=" + sd.Score);
+                                    }
+                                }
+                            }
+
+                            if (groupsResult == null)
+                            {
+                                Console.WriteLine("TEST: no matched groups");
+                            }
+                            else
+                            {
+                                Console.WriteLine("TEST: matched groups totalGroupedHitCount=" + groupsResult.TotalGroupedHitCount);
+                                foreach (GroupDocs<BytesRef> gd in groupsResult.Groups)
+                                {
+                                    Console.WriteLine("  group=" + (gd.GroupValue == null ? "null" : gd.GroupValue.Utf8ToString()) + " totalHits=" + gd.TotalHits);
+                                    foreach (ScoreDoc sd in gd.ScoreDocs)
+                                    {
+                                        Console.WriteLine("    id=" + docIDToID.Get(sd.Doc) + " score=" + sd.Score);
+                                    }
+                                }
+
+                                if (searchIter == 14)
+                                {
+                                    for (int docIDX = 0; docIDX < s.IndexReader.MaxDoc; docIDX++)
+                                    {
+                                        Console.WriteLine("ID=" + docIDToID.Get(docIDX) + " explain=" + s.Explain(query, docIDX));
+                                    }
+                                }
+                            }
+
+                            if (topGroupsShards == null)
+                            {
+                                Console.WriteLine("TEST: no matched-merged groups");
+                            }
+                            else
+                            {
+                                Console.WriteLine("TEST: matched-merged groups totalGroupedHitCount=" + topGroupsShards.TotalGroupedHitCount);
+                                foreach (GroupDocs<BytesRef> gd in topGroupsShards.Groups)
+                                {
+                                    Console.WriteLine("  group=" + (gd.GroupValue == null ? "null" : gd.GroupValue.Utf8ToString()) + " totalHits=" + gd.TotalHits);
+                                    foreach (ScoreDoc sd in gd.ScoreDocs)
+                                    {
+                                        Console.WriteLine("    id=" + docIDToID.Get(sd.Doc) + " score=" + sd.Score);
+                                    }
+                                }
+                            }
+                        }
+
+                        assertEquals(docIDToID, expectedGroups, groupsResult, true, true, true, getScores, groupField.EndsWith("_dv"));
+
+                        // Confirm merged shards match:
+                        assertEquals(docIDToID, expectedGroups, topGroupsShards, true, false, fillFields, getScores, idvBasedImplsUsedSharded.value);
+                        if (topGroupsShards != null)
+                        {
+                            verifyShards(shards.docStarts, topGroupsShards);
+                        }
+
+                        bool needsScores = getScores || getMaxScores || docSort == null;
+                        BlockGroupingCollector c3 = new BlockGroupingCollector(groupSort, groupOffset + topNGroups, needsScores, lastDocInBlock);
+                        TermAllGroupsCollector allGroupsCollector2;
+                        Collector c4;
+                        if (doAllGroups)
+                        {
+                            // NOTE: must be "group" and not "group_dv"
+                            // (groupField) because we didn't index doc
+                            // values in the block index:
+                            allGroupsCollector2 = new TermAllGroupsCollector("group");
+                            c4 = MultiCollector.Wrap(c3, allGroupsCollector2);
+                        }
+                        else
+                        {
+                            allGroupsCollector2 = null;
+                            c4 = c3;
+                        }
+                        // Get block grouping result:
+                        sBlocks.Search(query, c4);
+                        TopGroups<BytesRef> tempTopGroupsBlocks = (TopGroups<BytesRef>)c3.GetTopGroups<BytesRef>(docSort, groupOffset, docOffset, docOffset + docsPerGroup, fillFields);
+                        TopGroups<BytesRef> groupsResultBlocks;
+                        if (doAllGroups && tempTopGroupsBlocks != null)
+                        {
+                            assertEquals((int)tempTopGroupsBlocks.TotalGroupCount, allGroupsCollector2.GetGroupCount());
+                            groupsResultBlocks = new TopGroups<BytesRef>(tempTopGroupsBlocks, allGroupsCollector2.GetGroupCount());
+                        }
+                        else
+                        {
+                            groupsResultBlocks = tempTopGroupsBlocks;
+                        }
+
+                        if (VERBOSE)
+                        {
+                            if (groupsResultBlocks == null)
+                            {
+                                Console.WriteLine("TEST: no block groups");
+                            }
+                            else
+                            {
+                                Console.WriteLine("TEST: block groups totalGroupedHitCount=" + groupsResultBlocks.TotalGroupedHitCount);
+                                bool first = true;
+                                foreach (GroupDocs<BytesRef> gd in groupsResultBlocks.Groups)
+                                {
+                                    Console.WriteLine("  group=" + (gd.GroupValue == null ? "null" : gd.GroupValue.Utf8ToString()) + " totalHits=" + gd.TotalHits);
+                                    foreach (ScoreDoc sd in gd.ScoreDocs)
+                                    {
+                                        Console.WriteLine("    id=" + docIDToIDBlocks.Get(sd.Doc) + " score=" + sd.Score);
+                                        if (first)
+                                        {
+                                            Console.WriteLine("explain: " + sBlocks.Explain(query, sd.Doc));
+                                            first = false;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        // Get shard'd block grouping result:
+                        // Block index does not index DocValues so we pass
+                        // false for canUseIDV:
+                        TopGroups<BytesRef> topGroupsBlockShards = searchShards(sBlocks, shardsBlocks.subSearchers, query,
+                           groupSort, docSort, groupOffset, topNGroups, docOffset, docsPerGroup, getScores, getMaxScores, false, false, new ValueHolder<bool>(false));
+
+                        if (expectedGroups != null)
+                        {
+                            // Fixup scores for reader2
+                            foreach (var groupDocsHits in expectedGroups.Groups)
+                            {
+                                foreach (ScoreDoc hit in groupDocsHits.ScoreDocs)
+                                {
+                                    GroupDoc gd = groupDocsByID[hit.Doc];
+                                    assertEquals(gd.id, hit.Doc);
+                                    //Console.WriteLine("fixup score " + hit.score + " to " + gd.score2 + " vs " + gd.score);
+                                    hit.Score = gd.score2;
+                                }
+                            }
+
+                            SortField[] sortFields = groupSort.GetSort();
+                            IDictionary<float, float> termScoreMap = scoreMap[searchTerm];
+                            for (int groupSortIDX = 0; groupSortIDX < sortFields.Length; groupSortIDX++)
+                            {
+                                if (sortFields[groupSortIDX].Type == SortField.Type_e.SCORE)
+                                {
+                                    foreach (var groupDocsHits in expectedGroups.Groups)
+                                    {
+                                        if (groupDocsHits.GroupSortValues != null)
+                                        {
+                                            //Console.WriteLine("remap " + groupDocsHits.groupSortValues[groupSortIDX] + " to " + termScoreMap.get(groupDocsHits.groupSortValues[groupSortIDX]));
+                                            groupDocsHits.GroupSortValues[groupSortIDX] = termScoreMap[groupDocsHits.GroupSortValues[groupSortIDX]];
+                                            assertNotNull(groupDocsHits.GroupSortValues[groupSortIDX]);
+                                        }
+                                    }
+                                }
+                            }
+
+                            SortField[] docSortFields = docSort.GetSort();
+                            for (int docSortIDX = 0; docSortIDX < docSortFields.Length; docSortIDX++)
+                            {
+                                if (docSortFields[docSortIDX].Type == SortField.Type_e.SCORE)
+                                {
+                                    foreach (var groupDocsHits in expectedGroups.Groups)
+                                    {
+                                        foreach (ScoreDoc _hit in groupDocsHits.ScoreDocs)
+                                        {
+                                            FieldDoc hit = (FieldDoc)_hit;
+                                            if (hit.Fields != null)
+                                            {
+                                                hit.Fields[docSortIDX] = termScoreMap[hit.Fields[docSortIDX]];
+                                                assertNotNull(hit.Fields[docSortIDX]);
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        assertEquals(docIDToIDBlocks, expectedGroups, groupsResultBlocks, false, true, true, getScores, false);
+                        assertEquals(docIDToIDBlocks, expectedGroups, topGroupsBlockShards, false, false, fillFields, getScores, false);
+                    }
+                }
+                finally
+                {
+                    QueryUtils.PurgeFieldCache(r);
+                    if (rBlocks != null)
+                    {
+                        QueryUtils.PurgeFieldCache(rBlocks);
+                    }
+                }
+
+                r.Dispose();
+                dir.Dispose();
+
+                rBlocks.Dispose();
+                dirBlocks.Dispose();
+            }
+        }
+
+        private void verifyShards(int[] docStarts, TopGroups<BytesRef> topGroups)
+        {
+            foreach (var group in topGroups.Groups)
+            {
+                for (int hitIDX = 0; hitIDX < group.ScoreDocs.Length; hitIDX++)
+                {
+                    ScoreDoc sd = group.ScoreDocs[hitIDX];
+                    assertEquals("doc=" + sd.Doc + " wrong shard",
+                                 ReaderUtil.SubIndex(sd.Doc, docStarts),
+                                 sd.ShardIndex);
+                }
+            }
+        }
+
+        private TopGroups<BytesRef> searchShards(IndexSearcher topSearcher, ShardSearcher[] subSearchers, Query query, Sort groupSort, Sort docSort, int groupOffset, int topNGroups, int docOffset,
+                                                 int topNDocs, bool getScores, bool getMaxScores, bool canUseIDV, bool preFlex, ValueHolder<bool> usedIdvBasedImpl)
+        {
+
+            // TODO: swap in caching, all groups collector hereassertEquals(expected.totalHitCount, actual.totalHitCount);
+            // too...
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: " + subSearchers.Length + " shards: " + Arrays.ToString(subSearchers) + " canUseIDV=" + canUseIDV);
+            }
+            // Run 1st pass collector to get top groups per shard
+            Weight w = topSearcher.CreateNormalizedWeight(query);
+            List<ICollection<SearchGroup<BytesRef>>> shardGroups = new List<ICollection<SearchGroup<BytesRef>>>();
+            List < AbstractFirstPassGroupingCollector <?>> firstPassGroupingCollectors = new ArrayList<>();
+            AbstractFirstPassGroupingCollector <?> firstPassCollector = null;
+            bool shardsCanUseIDV;
+            if (canUseIDV)
+            {
+                if (typeof(SlowCompositeReaderWrapper).IsAssignableFrom(subSearchers[0].IndexReader.GetType()))
+                {
+                    shardsCanUseIDV = false;
+                }
+                else
+                {
+                    shardsCanUseIDV = !preFlex;
+                }
+            }
+            else
+            {
+                shardsCanUseIDV = false;
+            }
+
+            String groupField = "group";
+            if (shardsCanUseIDV && Random().nextBoolean())
+            {
+                groupField += "_dv";
+                usedIdvBasedImpl.value = true;
+            }
+
+            for (int shardIDX = 0; shardIDX < subSearchers.Length; shardIDX++)
+            {
+
+                // First shard determines whether we use IDV or not;
+                // all other shards match that:
+                if (firstPassCollector == null)
+                {
+                    firstPassCollector = createRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
+                }
+                else
+                {
+                    firstPassCollector = createFirstPassCollector(groupField, groupSort, groupOffset + topNGroups, firstPassCollector);
+                }
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  shard=" + shardIDX + " groupField=" + groupField);
+                    Console.WriteLine("    1st pass collector=" + firstPassCollector);
+                }
+                firstPassGroupingCollectors.Add(firstPassCollector);
+                subSearchers[shardIDX].Search(w, firstPassCollector);
+                ICollection<SearchGroup<BytesRef>> topGroups = getSearchGroups(firstPassCollector, 0, true);
+                if (topGroups != null)
+                {
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  shard " + shardIDX + " s=" + subSearchers[shardIDX] + " totalGroupedHitCount=?" + " " + topGroups.size() + " groups:");
+                        foreach (SearchGroup<BytesRef> group in topGroups)
+                        {
+                            Console.WriteLine("    " + groupToString(group.groupValue) + " groupSort=" + Arrays.ToString(group.sortValues));
+                        }
+                    }
+                    shardGroups.Add(topGroups);
+                }
+            }
+
+            ICollection<SearchGroup<BytesRef>> mergedTopGroups = SearchGroup<BytesRef>.Merge(shardGroups, groupOffset, topNGroups, groupSort);
+            if (VERBOSE)
+            {
+                Console.WriteLine(" top groups merged:");
+                if (mergedTopGroups == null)
+                {
+                    Console.WriteLine("    null");
+                }
+                else
+                {
+                    Console.WriteLine("    " + mergedTopGroups.size() + " top groups:");
+                    foreach (SearchGroup<BytesRef> group in mergedTopGroups)
+                    {
+                        Console.WriteLine("    [" + groupToString(group.groupValue) + "] groupSort=" + Arrays.ToString(group.sortValues));
+                    }
+                }
+            }
+
+            if (mergedTopGroups != null)
+            {
+                // Now 2nd pass:
+                TopGroups<BytesRef>[] shardTopGroups = new TopGroups<BytesRef>[subSearchers.Length];
+                for (int shardIDX = 0; shardIDX < subSearchers.Length; shardIDX++)
+                {
+                    AbstractSecondPassGroupingCollector <?> secondPassCollector = createSecondPassCollector(firstPassGroupingCollectors.get(shardIDX),
+                        groupField, mergedTopGroups, groupSort, docSort, docOffset + topNDocs, getScores, getMaxScores, true);
+                    subSearchers[shardIDX].Search(w, secondPassCollector);
+                    shardTopGroups[shardIDX] = getTopGroups(secondPassCollector, 0);
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine(" " + shardTopGroups[shardIDX].Groups.Length + " shard[" + shardIDX + "] groups:");
+                        foreach (GroupDocs<BytesRef> group in shardTopGroups[shardIDX].Groups)
+                        {
+                            Console.WriteLine("    [" + groupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.GroupSortValues) + " numDocs=" + group.ScoreDocs.Length);
+                        }
+                    }
+                }
+
+                // LUCENENET TODO: Put Merge() in a TopGroups class
+                TopGroups<BytesRef> mergedGroups = TopGroups<BytesRef>.Merge(shardTopGroups, groupSort, docSort, docOffset, topNDocs, TopGroups<BytesRef>.ScoreMergeMode.None);
+                if (VERBOSE)
+                {
+                    Console.WriteLine(" " + mergedGroups.Groups.Length + " merged groups:");
+                    foreach (GroupDocs<BytesRef> group in mergedGroups.Groups)
+                    {
+                        Console.WriteLine("    [" + groupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.GroupSortValues) + " numDocs=" + group.ScoreDocs.Length);
+                    }
+                }
+                return mergedGroups;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        private void assertEquals(FieldCache.Ints docIDtoID, TopGroups<BytesRef> expected, TopGroups<BytesRef> actual, bool verifyGroupValues, bool verifyTotalGroupCount, bool verifySortValues, bool testScores, bool idvBasedImplsUsed)
+        {
+            if (expected == null)
+            {
+                assertNull(actual);
+                return;
+            }
+            assertNotNull(actual);
+
+            assertEquals("expected.groups.length != actual.groups.length", expected.Groups.Length, actual.Groups.Length);
+            assertEquals("expected.totalHitCount != actual.totalHitCount", expected.TotalHitCount, actual.TotalHitCount);
+            assertEquals("expected.totalGroupedHitCount != actual.totalGroupedHitCount", expected.TotalGroupedHitCount, actual.TotalGroupedHitCount);
+            if (expected.TotalGroupCount != null && verifyTotalGroupCount)
+            {
+                assertEquals("expected.totalGroupCount != actual.totalGroupCount", expected.TotalGroupCount, actual.TotalGroupCount);
+            }
+
+            for (int groupIDX = 0; groupIDX < expected.Groups.Length; groupIDX++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  check groupIDX=" + groupIDX);
+                }
+                GroupDocs<BytesRef> expectedGroup = expected.Groups[groupIDX];
+                GroupDocs<BytesRef> actualGroup = actual.Groups[groupIDX];
+                if (verifyGroupValues)
+                {
+                    if (idvBasedImplsUsed)
+                    {
+                        if (actualGroup.GroupValue.Length == 0)
+                        {
+                            assertNull(expectedGroup.GroupValue);
+                        }
+                        else
+                        {
+                            assertEquals(expectedGroup.GroupValue, actualGroup.GroupValue);
+                        }
+                    }
+                    else
+                    {
+                        assertEquals(expectedGroup.GroupValue, actualGroup.GroupValue);
+                    }
+
+                }
+                if (verifySortValues)
+                {
+                    assertArrayEquals(expectedGroup.GroupSortValues, actualGroup.GroupSortValues);
+                }
+
+                // TODO
+                // assertEquals(expectedGroup.maxScore, actualGroup.maxScore);
+                assertEquals(expectedGroup.TotalHits, actualGroup.TotalHits);
+
+                ScoreDoc[] expectedFDs = expectedGroup.ScoreDocs;
+                ScoreDoc[] actualFDs = actualGroup.ScoreDocs;
+
+                assertEquals(expectedFDs.Length, actualFDs.Length);
+                for (int docIDX = 0; docIDX < expectedFDs.Length; docIDX++)
+                {
+                    FieldDoc expectedFD = (FieldDoc)expectedFDs[docIDX];
+                    FieldDoc actualFD = (FieldDoc)actualFDs[docIDX];
+                    //Console.WriteLine("  actual doc=" + docIDtoID.get(actualFD.doc) + " score=" + actualFD.score);
+                    assertEquals(expectedFD.Doc, docIDtoID.Get(actualFD.Doc));
+                    if (testScores)
+                    {
+                        assertEquals(expectedFD.Score, actualFD.Score, 0.1);
+                    }
+                    else
+                    {
+                        // TODO: too anal for now
+                        //assertEquals(Float.NaN, actualFD.score);
+                    }
+                    if (verifySortValues)
+                    {
+                        assertArrayEquals(expectedFD.Fields, actualFD.Fields);
+                    }
+                }
+            }
+        }
+
+        internal class ShardSearcher : IndexSearcher
+        {
+            private readonly List<AtomicReaderContext> ctx;
+
+            public ShardSearcher(AtomicReaderContext ctx, IndexReaderContext parent)
+                            : base(parent)
+            {
+                this.ctx = Collections.SingletonList(ctx);
+            }
+
+            public void Search(Weight weight, Collector collector)
+            {
+                Search(ctx, weight, collector);
+            }
+
+            public override string ToString()
+            {
+                return "ShardSearcher(" + ctx[0].Reader + ")";
+            }
+        }
+
+        internal class ValueHolder<V>
+        {
+
+            internal V value;
+
+            internal ValueHolder(V value)
+            {
+                this.value = value;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9d72bcb3/src/Lucene.Net.Tests.Grouping/packages.config
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/packages.config b/src/Lucene.Net.Tests.Grouping/packages.config
new file mode 100644
index 0000000..139d513
--- /dev/null
+++ b/src/Lucene.Net.Tests.Grouping/packages.config
@@ -0,0 +1,4 @@
+\ufeff<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NUnit" version="2.6.3" targetFramework="net451" />
+</packages>
\ No newline at end of file


[11/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
Added TreeSet and TreeDictionary from C5 to the Support namespace


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

Branch: refs/heads/grouping
Commit: 5f198526ed04616007e8baa03480fa7df327c1b3
Parents: 0844f41
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Oct 27 18:43:54 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Mon Nov 7 18:44:01 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Lucene.Net.csproj           |    3 +
 src/Lucene.Net.Core/Support/C5.Support.cs       | 7335 ++++++++++++++++++
 src/Lucene.Net.Core/Support/TreeDictionary.cs   |   74 +
 src/Lucene.Net.Core/Support/TreeSet.cs          | 3752 +++++++++
 src/Lucene.Net.Tests/Lucene.Net.Tests.csproj    |   12 +
 .../core/Support/C5/ArrayBase.cs                |  479 ++
 .../core/Support/C5/ArrayList.cs                | 2248 ++++++
 .../core/Support/C5/DropMultiplicity.cs         |   15 +
 src/Lucene.Net.Tests/core/Support/C5/Events.cs  |  893 +++
 .../core/Support/C5/GenericCollectionTester.cs  |   87 +
 src/Lucene.Net.Tests/core/Support/C5/HashBag.cs |  658 ++
 src/Lucene.Net.Tests/core/Support/C5/Sorting.cs |  235 +
 .../core/Support/C5/SupportClasses.cs           |  506 ++
 .../core/Support/C5/WeakViewList.cs             |  101 +
 .../core/Support/C5/Wrappers.cs                 | 2338 ++++++
 .../core/Support/TestTreeDictionary.cs          |  522 ++
 .../core/Support/TestTreeSet.cs                 | 2970 +++++++
 17 files changed, 22228 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Core/Lucene.Net.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Lucene.Net.csproj b/src/Lucene.Net.Core/Lucene.Net.csproj
index 39bf69e..09915fb 100644
--- a/src/Lucene.Net.Core/Lucene.Net.csproj
+++ b/src/Lucene.Net.Core/Lucene.Net.csproj
@@ -617,6 +617,7 @@
     <Compile Include="Support\ByteArrayOutputStream.cs" />
     <Compile Include="Support\ByteBuffer.cs" />
     <Compile Include="Support\ByteOrder.cs" />
+    <Compile Include="Support\C5.Support.cs" />
     <Compile Include="Support\Character.cs" />
     <Compile Include="Support\Arrays.cs" />
     <Compile Include="Support\CharacterIterator.cs" />
@@ -659,6 +660,8 @@
     <Compile Include="Support\TaskSchedulerCompletionService.cs" />
     <Compile Include="Support\ThreadFactory.cs" />
     <Compile Include="Support\TimeHelper.cs" />
+    <Compile Include="Support\TreeDictionary.cs" />
+    <Compile Include="Support\TreeSet.cs" />
     <Compile Include="Support\UnmodifiableDictionary.cs" />
     <Compile Include="Support\CloseableThreadLocalProfiler.cs" />
     <Compile Include="Support\CollectionsHelper.cs" />


[35/58] [abbrv] lucenenet git commit: Added StringBuilder.AppendCodePoint() extension method to Core.Support.StringBuilderExtensions + added unit tests. Fixed buggy StringBuilder.Reverse() method to account for Unicode.

Posted by ni...@apache.org.
Added StringBuilder.AppendCodePoint() extension method to Core.Support.StringBuilderExtensions + added unit tests. Fixed buggy StringBuilder.Reverse() method to account for Unicode.


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

Branch: refs/heads/grouping
Commit: 081ce8c35473e96025d5631ffa929f94847ecf18
Parents: 8af1037
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Nov 3 18:18:25 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:53 2016 +0700

----------------------------------------------------------------------
 .../Support/StringBuilderExtensions.cs          | 57 +++++++++++++---
 src/Lucene.Net.Tests/Lucene.Net.Tests.csproj    |  1 +
 .../core/Support/TestStringBuilderExtensions.cs | 72 ++++++++++++++++++++
 3 files changed, 121 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/081ce8c3/src/Lucene.Net.Core/Support/StringBuilderExtensions.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/StringBuilderExtensions.cs b/src/Lucene.Net.Core/Support/StringBuilderExtensions.cs
index 728ff60..8164939 100644
--- a/src/Lucene.Net.Core/Support/StringBuilderExtensions.cs
+++ b/src/Lucene.Net.Core/Support/StringBuilderExtensions.cs
@@ -1,4 +1,5 @@
-\ufeffusing System.Text;
+\ufeffusing System.Globalization;
+using System.Text;
 
 namespace Lucene.Net.Support
 {
@@ -6,20 +7,58 @@ namespace Lucene.Net.Support
     {
         public static StringBuilder Reverse(this StringBuilder text)
         {
-            if (text.Length > 1)
+            int textLength = text.Length;
+            if (textLength > 1)
             {
-                int pivotPos = text.Length / 2;
-                for (int i = 0; i < pivotPos; i++)
+                // Pull the string out of the StringBuilder so we
+                // can work with the various text elements (chars, glyphs, graphemes, etc)
+                // and reverse the order of the string without reversing chars that need to be
+                // in a specific order to represent the same text as the forward string.
+                // Reference: http://stackoverflow.com/a/36310993/181087
+                int offset = textLength;
+                var enumerator = StringInfo.GetTextElementEnumerator(text.ToString());
+                while (enumerator.MoveNext())
                 {
-                    int iRight = text.Length - (i + 1);
-                    char rightChar = text[i];
-                    char leftChar = text[iRight];
-                    text[i] = leftChar;
-                    text[iRight] = rightChar;
+                    string element = enumerator.GetTextElement();
+
+                    // Back up the current offset by the length of the element
+                    offset -= element.Length;
+
+                    for (int i = 0; i < element.Length; i++)
+                    {
+                        // Write the chars in forward order from the element
+                        // to the StringBuilder based on the offset.
+                        text[i + offset] = element[i];
+                    }
                 }
             }
 
             return text;
         }
+
+        /// <summary>
+        /// Appends the string representation of the <paramref name="codePoint"/>
+        /// argument to this sequence.
+        /// 
+        /// <para>
+        /// The argument is appended to the contents of this sequence.
+        /// The length of this sequence increases by <see cref="Character.CharCount(int)"/>.
+        /// </para>
+        /// <para>
+        /// The overall effect is exactly as if the argument were
+        /// converted to a <see cref="char"/> array by the method
+        /// <see cref="Character.ToChars(int)"/> and the character in that array
+        /// were then <see cref="StringBuilder.Append(char[])">appended</see> to this 
+        /// <see cref="StringBuilder"/>.
+        /// </para>
+        /// </summary>
+        /// <param name="text">This <see cref="StringBuilder"/>.</param>
+        /// <param name="codePoint">a Unicode code point</param>
+        /// <returns>a reference to this object.</returns>
+        public static StringBuilder AppendCodePoint(this StringBuilder text, int codePoint)
+        {
+            text.Append(Character.ToChars(codePoint));
+            return text;
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/081ce8c3/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 9e6377e..00a14dc 100644
--- a/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
+++ b/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
@@ -491,6 +491,7 @@
     <Compile Include="core\Support\TestLurchTableThreading.cs" />
     <Compile Include="core\Support\TestDataInputStream.cs" />
     <Compile Include="core\Support\TestDataOutputStream.cs" />
+    <Compile Include="core\Support\TestStringBuilderExtensions.cs" />
     <Compile Include="core\Support\TestTreeDictionary.cs" />
     <Compile Include="core\Support\TestTreeSet.cs" />
     <Compile Include="core\TestAssertions.cs">

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/081ce8c3/src/Lucene.Net.Tests/core/Support/TestStringBuilderExtensions.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestStringBuilderExtensions.cs b/src/Lucene.Net.Tests/core/Support/TestStringBuilderExtensions.cs
new file mode 100644
index 0000000..f7c23d0
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/TestStringBuilderExtensions.cs
@@ -0,0 +1,72 @@
+\ufeffusing Lucene.Net.Attributes;
+using NUnit.Framework;
+using System;
+using System.Text;
+
+namespace Lucene.Net.Support
+{
+    [TestFixture]
+    public class TestStringBuilderExtensions
+    {
+        [Test, LuceneNetSpecific]
+        public virtual void TestReverse()
+        {
+            var sb = new StringBuilder("foo \U0001d306 bar\U0002b001ma�ana");
+
+            sb.Reverse();
+
+            Assert.AreEqual("ana�am\U0002b001rab \U0001d306 oof", sb.ToString());
+        }
+
+        [Test, LuceneNetSpecific]
+        public virtual void TestAppendCodePointBmp()
+        {
+            var sb = new StringBuilder("foo bar");
+            int codePoint = 97; // a
+
+            sb.AppendCodePoint(codePoint);
+
+            Assert.AreEqual("foo bara", sb.ToString());
+        }
+
+        [Test, LuceneNetSpecific]
+        public virtual void TestAppendCodePointUnicode()
+        {
+            var sb = new StringBuilder("foo bar");
+            int codePoint = 3594; // \u0e0a
+
+            sb.AppendCodePoint(codePoint);
+
+            Assert.AreEqual("foo bar\u0e0a", sb.ToString());
+        }
+
+        [Test, LuceneNetSpecific]
+        public virtual void TestAppendCodePointUTF16Surrogates()
+        {
+            var sb = new StringBuilder("foo bar");
+            int codePoint = 176129; // '\uD86C', '\uDC01' (\U0002b001)
+
+            sb.AppendCodePoint(codePoint);
+
+            Assert.AreEqual("foo bar\U0002b001", sb.ToString());
+        }
+
+        [Test, LuceneNetSpecific]
+        public virtual void TestAppendCodePointTooHigh()
+        {
+            var sb = new StringBuilder("foo bar");
+            int codePoint = Character.MAX_CODE_POINT + 1;
+
+            Assert.Throws<ArgumentException>(() => sb.AppendCodePoint(codePoint));
+        }
+
+        [Test, LuceneNetSpecific]
+        public virtual void TestAppendCodePointTooLow()
+        {
+            var sb = new StringBuilder("foo bar");
+            int codePoint = Character.MIN_CODE_POINT - 1;
+
+            Assert.Throws<ArgumentException>(() => sb.AppendCodePoint(codePoint));
+        }
+    }
+}


[14/58] [abbrv] lucenenet git commit: Added object overrides to Core.Support.HashMap so it can be used as a dictionary key based on values within the dictionary rather than by reference equality.

Posted by ni...@apache.org.
Added object overrides to Core.Support.HashMap so it can be used as a dictionary key based on values within the dictionary rather than by reference equality.


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

Branch: refs/heads/grouping
Commit: 63fa4caff3c10f2e9ad9c63c6b24043534f8a2a6
Parents: dc8a4b8
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sat Nov 5 16:51:13 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Mon Nov 7 18:44:13 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Support/HashMap.cs | 78 +++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/63fa4caf/src/Lucene.Net.Core/Support/HashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/HashMap.cs b/src/Lucene.Net.Core/Support/HashMap.cs
index addd506..0fcf29a 100644
--- a/src/Lucene.Net.Core/Support/HashMap.cs
+++ b/src/Lucene.Net.Core/Support/HashMap.cs
@@ -125,6 +125,84 @@ namespace Lucene.Net.Support
             return this[key];
         }
 
+        #region Object overrides
+
+        public override bool Equals(object obj)
+        {
+            if (obj == this)
+                return true;
+
+            if (!(obj is IDictionary<TKey, TValue>))
+                return false;
+            IDictionary<TKey, TValue> m = (IDictionary<TKey, TValue>)obj;
+            if (m.Count != Count)
+                return false;
+
+            try
+            {
+                var i = GetEnumerator();
+                while (i.MoveNext())
+                {
+                    KeyValuePair<TKey, TValue> e = i.Current;
+                    TKey key = e.Key;
+                    TValue value = e.Value;
+                    if (value == null)
+                    {
+                        if (!(m[key] == null && m.ContainsKey(key)))
+                            return false;
+                    }
+                    else
+                    {
+                        if (!value.Equals(m[key]))
+                            return false;
+                    }
+                }
+            }
+            catch (InvalidCastException)
+            {
+                return false;
+            }
+            catch (NullReferenceException)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public override int GetHashCode()
+        {
+            int h = 0;
+            var i = GetEnumerator();
+            while (i.MoveNext())
+                h += i.Current.GetHashCode();
+            return h;
+        }
+
+        public override string ToString()
+        {
+            var i = GetEnumerator();
+            if (!i.MoveNext())
+                return "{}";
+
+            StringBuilder sb = new StringBuilder();
+            sb.Append('{');
+            for (;;)
+            {
+                var e = i.Current;
+                TKey key = e.Key;
+                TValue value = e.Value;
+                sb.Append(key);
+                sb.Append('=');
+                sb.Append(value);
+                if (!i.MoveNext())
+                    return sb.Append('}').ToString();
+                sb.Append(',').Append(' ');
+            }
+        }
+
+        #endregion
+
         #region Implementation of IEnumerable
 
         public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()


[02/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/TestTreeDictionary.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestTreeDictionary.cs b/src/Lucene.Net.Tests/core/Support/TestTreeDictionary.cs
new file mode 100644
index 0000000..2ea7c90
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/TestTreeDictionary.cs
@@ -0,0 +1,522 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using Lucene.Net.Attributes;
+using Lucene.Net.Support.C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace Lucene.Net.Support.RBDictionary
+{
+    using DictionaryIntToInt = TreeDictionary<int, int>;
+
+    static class Factory
+    {
+        public static IDictionary<K, V> New<K, V>() { return new TreeDictionary<K, V>(); }
+    }
+
+    //[TestFixture]
+    //public class GenericTesters
+    //{
+    //    [Test, LuceneNetSpecific]
+    //    public void TestSerialize()
+    //    {
+    //        C5UnitTests.Templates.Extensible.Serialization.DTester<DictionaryIntToInt>();
+    //    }
+    //}
+
+
+    [TestFixture]
+    public class Formatting
+    {
+        IDictionary<int, int> coll;
+        IFormatProvider rad16;
+        [SetUp]
+        public void Init() { coll = Factory.New<int, int>(); rad16 = new RadixFormatProvider(16); }
+        [TearDown]
+        public void Dispose() { coll = null; rad16 = null; }
+        [Test, LuceneNetSpecific]
+        public void Format()
+        {
+            Assert.AreEqual("[  ]", coll.ToString());
+            coll.Add(23, 67); coll.Add(45, 89);
+            Assert.AreEqual("[ 23 => 67, 45 => 89 ]", coll.ToString());
+            Assert.AreEqual("[ 17 => 43, 2D => 59 ]", coll.ToString(null, rad16));
+            Assert.AreEqual("[ 23 => 67, ... ]", coll.ToString("L14", null));
+            Assert.AreEqual("[ 17 => 43, ... ]", coll.ToString("L14", rad16));
+        }
+    }
+
+    [TestFixture]
+    public class RBDict
+    {
+        private TreeDictionary<string, string> dict;
+
+
+        [SetUp]
+        public void Init() { dict = new TreeDictionary<string, string>(new SC()); }
+
+
+        [TearDown]
+        public void Dispose() { dict = null; }
+
+        [Test, LuceneNetSpecific]
+        public void NullEqualityComparerinConstructor1()
+        {
+            Assert.Throws<NullReferenceException>(() => new TreeDictionary<int, int>(null));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Choose()
+        {
+            dict.Add("YES", "NO");
+            Assert.AreEqual(new KeyValuePair<string, string>("YES", "NO"), dict.Choose());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void BadChoose()
+        {
+            Assert.Throws<NoSuchItemException>(() => dict.Choose());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Pred1()
+        {
+            dict.Add("A", "1");
+            dict.Add("C", "2");
+            dict.Add("E", "3");
+            Assert.AreEqual("1", dict.Predecessor("B").Value);
+            Assert.AreEqual("1", dict.Predecessor("C").Value);
+            Assert.AreEqual("1", dict.WeakPredecessor("B").Value);
+            Assert.AreEqual("2", dict.WeakPredecessor("C").Value);
+            Assert.AreEqual("2", dict.Successor("B").Value);
+            Assert.AreEqual("3", dict.Successor("C").Value);
+            Assert.AreEqual("2", dict.WeakSuccessor("B").Value);
+            Assert.AreEqual("2", dict.WeakSuccessor("C").Value);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Pred2()
+        {
+            dict.Add("A", "1");
+            dict.Add("C", "2");
+            dict.Add("E", "3");
+            KeyValuePair<String, String> res;
+            Assert.IsTrue(dict.TryPredecessor("B", out res));
+            Assert.AreEqual("1", res.Value);
+            Assert.IsTrue(dict.TryPredecessor("C", out res));
+            Assert.AreEqual("1", res.Value);
+            Assert.IsTrue(dict.TryWeakPredecessor("B", out res));
+            Assert.AreEqual("1", res.Value);
+            Assert.IsTrue(dict.TryWeakPredecessor("C", out res));
+            Assert.AreEqual("2", res.Value);
+            Assert.IsTrue(dict.TrySuccessor("B", out res));
+            Assert.AreEqual("2", res.Value);
+            Assert.IsTrue(dict.TrySuccessor("C", out res));
+            Assert.AreEqual("3", res.Value);
+            Assert.IsTrue(dict.TryWeakSuccessor("B", out res));
+            Assert.AreEqual("2", res.Value);
+            Assert.IsTrue(dict.TryWeakSuccessor("C", out res));
+            Assert.AreEqual("2", res.Value);
+
+            Assert.IsFalse(dict.TryPredecessor("A", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+
+            Assert.IsFalse(dict.TryWeakPredecessor("@", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+
+            Assert.IsFalse(dict.TrySuccessor("E", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+
+            Assert.IsFalse(dict.TryWeakSuccessor("F", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Initial()
+        {
+            bool res;
+            Assert.IsFalse(dict.IsReadOnly);
+
+            Assert.AreEqual(dict.Count, 0, "new dict should be empty");
+            dict.Add("A", "B");
+            Assert.AreEqual(dict.Count, 1, "bad count");
+            Assert.AreEqual(dict["A"], "B", "Wrong value for dict[A]");
+            dict.Add("C", "D");
+            Assert.AreEqual(dict.Count, 2, "bad count");
+            Assert.AreEqual(dict["A"], "B", "Wrong value");
+            Assert.AreEqual(dict["C"], "D", "Wrong value");
+            res = dict.Remove("A");
+            Assert.IsTrue(res, "bad return value from Remove(A)");
+            Assert.IsTrue(dict.Check());
+            Assert.AreEqual(dict.Count, 1, "bad count");
+            Assert.AreEqual(dict["C"], "D", "Wrong value of dict[C]");
+            res = dict.Remove("Z");
+            Assert.IsFalse(res, "bad return value from Remove(Z)");
+            Assert.AreEqual(dict.Count, 1, "bad count");
+            Assert.AreEqual(dict["C"], "D", "Wrong value of dict[C] (2)");
+            dict.Clear();
+            Assert.AreEqual(dict.Count, 0, "dict should be empty");
+        }
+        [Test, LuceneNetSpecific]
+        public void Contains()
+        {
+            dict.Add("C", "D");
+            Assert.IsTrue(dict.Contains("C"));
+            Assert.IsFalse(dict.Contains("D"));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void IllegalAdd()
+        {
+            dict.Add("A", "B");
+
+            var exception = Assert.Throws<DuplicateNotAllowedException>(() => dict.Add("A", "B"));
+            Assert.AreEqual("Key being added: 'A'", exception.Message);
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void GettingNonExisting()
+        {
+            Assert.Throws<NoSuchItemException>(() => Console.WriteLine(dict["R"]));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void Setter()
+        {
+            dict["R"] = "UYGUY";
+            Assert.AreEqual(dict["R"], "UYGUY");
+            dict["R"] = "UIII";
+            Assert.AreEqual(dict["R"], "UIII");
+            dict["S"] = "VVV";
+            Assert.AreEqual(dict["R"], "UIII");
+            Assert.AreEqual(dict["S"], "VVV");
+            //dict.dump();
+        }
+    }
+
+    [TestFixture]
+    public class GuardedSortedDictionaryTest
+    {
+        private GuardedSortedDictionary<string, string> dict;
+
+        [SetUp]
+        public void Init()
+        {
+            ISortedDictionary<string, string> dict = new TreeDictionary<string, string>(new SC());
+            dict.Add("A", "1");
+            dict.Add("C", "2");
+            dict.Add("E", "3");
+            this.dict = new GuardedSortedDictionary<string, string>(dict);
+        }
+
+        [TearDown]
+        public void Dispose() { dict = null; }
+
+        [Test, LuceneNetSpecific]
+        public void Pred1()
+        {
+            Assert.AreEqual("1", dict.Predecessor("B").Value);
+            Assert.AreEqual("1", dict.Predecessor("C").Value);
+            Assert.AreEqual("1", dict.WeakPredecessor("B").Value);
+            Assert.AreEqual("2", dict.WeakPredecessor("C").Value);
+            Assert.AreEqual("2", dict.Successor("B").Value);
+            Assert.AreEqual("3", dict.Successor("C").Value);
+            Assert.AreEqual("2", dict.WeakSuccessor("B").Value);
+            Assert.AreEqual("2", dict.WeakSuccessor("C").Value);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Pred2()
+        {
+            KeyValuePair<String, String> res;
+            Assert.IsTrue(dict.TryPredecessor("B", out res));
+            Assert.AreEqual("1", res.Value);
+            Assert.IsTrue(dict.TryPredecessor("C", out res));
+            Assert.AreEqual("1", res.Value);
+            Assert.IsTrue(dict.TryWeakPredecessor("B", out res));
+            Assert.AreEqual("1", res.Value);
+            Assert.IsTrue(dict.TryWeakPredecessor("C", out res));
+            Assert.AreEqual("2", res.Value);
+            Assert.IsTrue(dict.TrySuccessor("B", out res));
+            Assert.AreEqual("2", res.Value);
+            Assert.IsTrue(dict.TrySuccessor("C", out res));
+            Assert.AreEqual("3", res.Value);
+            Assert.IsTrue(dict.TryWeakSuccessor("B", out res));
+            Assert.AreEqual("2", res.Value);
+            Assert.IsTrue(dict.TryWeakSuccessor("C", out res));
+            Assert.AreEqual("2", res.Value);
+
+            Assert.IsFalse(dict.TryPredecessor("A", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+
+            Assert.IsFalse(dict.TryWeakPredecessor("@", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+
+            Assert.IsFalse(dict.TrySuccessor("E", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+
+            Assert.IsFalse(dict.TryWeakSuccessor("F", out res));
+            Assert.AreEqual(null, res.Key);
+            Assert.AreEqual(null, res.Value);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Initial()
+        {
+            Assert.IsTrue(dict.IsReadOnly);
+
+            Assert.AreEqual(3, dict.Count);
+            Assert.AreEqual("1", dict["A"]);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Contains()
+        {
+            Assert.IsTrue(dict.Contains("A"));
+            Assert.IsFalse(dict.Contains("1"));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void IllegalAdd()
+        {
+            Assert.Throws<ReadOnlyCollectionException>(() => dict.Add("Q", "7"));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void IllegalClear()
+        {
+            Assert.Throws<ReadOnlyCollectionException>(() => dict.Clear());
+        }
+        [Test, LuceneNetSpecific]
+
+        public void IllegalSet()
+        {
+            Assert.Throws<ReadOnlyCollectionException>(() => dict["A"] = "8");
+        }
+
+        public void IllegalRemove()
+        {
+            Assert.Throws<ReadOnlyCollectionException>(() => dict.Remove("A"));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void GettingNonExisting()
+        {
+            Assert.Throws<NoSuchItemException>(() => Console.WriteLine(dict["R"]));
+        }
+    }
+
+    [TestFixture]
+    public class Enumerators
+    {
+        private TreeDictionary<string, string> dict;
+
+        private SCG.IEnumerator<KeyValuePair<string, string>> dictenum;
+
+
+        [SetUp]
+        public void Init()
+        {
+            dict = new TreeDictionary<string, string>(new SC());
+            dict["S"] = "A";
+            dict["T"] = "B";
+            dict["R"] = "C";
+            dictenum = dict.GetEnumerator();
+        }
+
+
+        [TearDown]
+        public void Dispose()
+        {
+            dictenum = null;
+            dict = null;
+        }
+
+        [Test, LuceneNetSpecific]
+        public void KeysEnumerator()
+        {
+            SCG.IEnumerator<string> keys = dict.Keys.GetEnumerator();
+            Assert.AreEqual(3, dict.Keys.Count);
+            Assert.IsTrue(keys.MoveNext());
+            Assert.AreEqual("R", keys.Current);
+            Assert.IsTrue(keys.MoveNext());
+            Assert.AreEqual("S", keys.Current);
+            Assert.IsTrue(keys.MoveNext());
+            Assert.AreEqual("T", keys.Current);
+            Assert.IsFalse(keys.MoveNext());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void KeysISorted()
+        {
+            ISorted<string> keys = dict.Keys;
+            Assert.IsTrue(keys.IsReadOnly);
+            Assert.AreEqual("R", keys.FindMin());
+            Assert.AreEqual("T", keys.FindMax());
+            Assert.IsTrue(keys.Contains("S"));
+            Assert.AreEqual(3, keys.Count);
+            // This doesn't hold, maybe because the dict uses a special key comparer?
+            // Assert.IsTrue(keys.SequencedEquals(new WrappedArray<string>(new string[] { "R", "S", "T" })));
+            Assert.IsTrue(keys.UniqueItems().All(delegate (String s) { return s == "R" || s == "S" || s == "T"; }));
+            Assert.IsTrue(keys.All(delegate (String s) { return s == "R" || s == "S" || s == "T"; }));
+            Assert.IsFalse(keys.Exists(delegate (String s) { return s != "R" && s != "S" && s != "T"; }));
+            String res;
+            Assert.IsTrue(keys.Find(delegate (String s) { return s == "R"; }, out res));
+            Assert.AreEqual("R", res);
+            Assert.IsFalse(keys.Find(delegate (String s) { return s == "Q"; }, out res));
+            Assert.AreEqual(null, res);
+        }
+
+        [Test, LuceneNetSpecific]
+        public void KeysISortedPred()
+        {
+            ISorted<string> keys = dict.Keys;
+            String res;
+            Assert.IsTrue(keys.TryPredecessor("S", out res));
+            Assert.AreEqual("R", res);
+            Assert.IsTrue(keys.TryWeakPredecessor("R", out res));
+            Assert.AreEqual("R", res);
+            Assert.IsTrue(keys.TrySuccessor("S", out res));
+            Assert.AreEqual("T", res);
+            Assert.IsTrue(keys.TryWeakSuccessor("T", out res));
+            Assert.AreEqual("T", res);
+            Assert.IsFalse(keys.TryPredecessor("R", out res));
+            Assert.AreEqual(null, res);
+            Assert.IsFalse(keys.TryWeakPredecessor("P", out res));
+            Assert.AreEqual(null, res);
+            Assert.IsFalse(keys.TrySuccessor("T", out res));
+            Assert.AreEqual(null, res);
+            Assert.IsFalse(keys.TryWeakSuccessor("U", out res));
+            Assert.AreEqual(null, res);
+
+            Assert.AreEqual("R", keys.Predecessor("S"));
+            Assert.AreEqual("R", keys.WeakPredecessor("R"));
+            Assert.AreEqual("T", keys.Successor("S"));
+            Assert.AreEqual("T", keys.WeakSuccessor("T"));
+        }
+
+        [Test, LuceneNetSpecific]
+        public void ValuesEnumerator()
+        {
+            SCG.IEnumerator<string> values = dict.Values.GetEnumerator();
+            Assert.AreEqual(3, dict.Values.Count);
+            Assert.IsTrue(values.MoveNext());
+            Assert.AreEqual("C", values.Current);
+            Assert.IsTrue(values.MoveNext());
+            Assert.AreEqual("A", values.Current);
+            Assert.IsTrue(values.MoveNext());
+            Assert.AreEqual("B", values.Current);
+            Assert.IsFalse(values.MoveNext());
+        }
+
+        [Test, LuceneNetSpecific]
+        public void Fun()
+        {
+            Assert.AreEqual("B", dict.Func("T"));
+        }
+
+
+        [Test, LuceneNetSpecific]
+        public void NormalUse()
+        {
+            Assert.IsTrue(dictenum.MoveNext());
+            Assert.AreEqual(dictenum.Current, new KeyValuePair<string, string>("R", "C"));
+            Assert.IsTrue(dictenum.MoveNext());
+            Assert.AreEqual(dictenum.Current, new KeyValuePair<string, string>("S", "A"));
+            Assert.IsTrue(dictenum.MoveNext());
+            Assert.AreEqual(dictenum.Current, new KeyValuePair<string, string>("T", "B"));
+            Assert.IsFalse(dictenum.MoveNext());
+        }
+    }
+
+
+    namespace PathCopyPersistence
+    {
+        [TestFixture]
+        public class Simple
+        {
+            private TreeDictionary<string, string> dict;
+
+            private TreeDictionary<string, string> snap;
+
+
+            [SetUp]
+            public void Init()
+            {
+                dict = new TreeDictionary<string, string>(new SC());
+                dict["S"] = "A";
+                dict["T"] = "B";
+                dict["R"] = "C";
+                dict["V"] = "G";
+                snap = (TreeDictionary<string, string>)dict.Snapshot();
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void Test()
+            {
+                dict["SS"] = "D";
+                Assert.AreEqual(5, dict.Count);
+                Assert.AreEqual(4, snap.Count);
+                dict["T"] = "bb";
+                Assert.AreEqual(5, dict.Count);
+                Assert.AreEqual(4, snap.Count);
+                Assert.AreEqual("B", snap["T"]);
+                Assert.AreEqual("bb", dict["T"]);
+                Assert.IsFalse(dict.IsReadOnly);
+                Assert.IsTrue(snap.IsReadOnly);
+                //Finally, update of root node:
+                TreeDictionary<string, string> snap2 = (TreeDictionary<string, string>)dict.Snapshot();
+                dict["S"] = "abe";
+                Assert.AreEqual("abe", dict["S"]);
+            }
+
+
+            [Test, LuceneNetSpecific]
+            public void UpdateSnap()
+            {
+                Assert.Throws<ReadOnlyCollectionException>(() => snap["Y"] = "J");
+            }
+
+
+            [TearDown]
+            public void Dispose()
+            {
+                dict = null;
+                snap = null;
+            }
+        }
+    }
+}
+


[34/58] [abbrv] lucenenet git commit: Fixed bug in TestFramework.Util.TestUtil.RandomRealisticUnicodeString() method that wasn't converting the code points into characters (so we were just getting random sequences of numbers instead of Unicode).

Posted by ni...@apache.org.
Fixed bug in TestFramework.Util.TestUtil.RandomRealisticUnicodeString() method that wasn't converting the code points into characters (so we were just getting random sequences of numbers instead of Unicode).


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

Branch: refs/heads/grouping
Commit: c3abdc7398d0ac1d0c09dc8b30362d62b99eefe4
Parents: 081ce8c
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Nov 3 18:20:03 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:53 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.TestFramework/Util/TestUtil.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c3abdc73/src/Lucene.Net.TestFramework/Util/TestUtil.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Util/TestUtil.cs b/src/Lucene.Net.TestFramework/Util/TestUtil.cs
index 72a55f2..a62f80a 100644
--- a/src/Lucene.Net.TestFramework/Util/TestUtil.cs
+++ b/src/Lucene.Net.TestFramework/Util/TestUtil.cs
@@ -746,7 +746,7 @@ namespace Lucene.Net.Util
             StringBuilder sb = new StringBuilder();
             for (int i = 0; i < end; i++)
             {
-                sb.Append(NextInt(r, BlockStarts[block], BlockEnds[block]));
+                sb.AppendCodePoint(NextInt(r, BlockStarts[block], BlockEnds[block]));
             }
             return sb.ToString();
         }


[19/58] [abbrv] lucenenet git commit: Revert "HACK: Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context."

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
index 889f963..ace0574 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
@@ -35,506 +35,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
index 0bfd3d7..990e29c 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
@@ -36,68 +36,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
index 910584c..6f30a01 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
@@ -35,68 +35,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
index eb47d6c..ddb99c6 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
@@ -35,68 +35,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
index 7e094fd..cac7e77 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
@@ -35,68 +35,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
index 13afde6..e9beed4 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
@@ -35,68 +35,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
index 33895b1..4f65807 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
@@ -40,531 +40,5 @@ namespace Lucene.Net.Codecs.Memory
         {
             return false;
         }
-
-
-        #region BaseCompressingDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestUniqueValuesCompression()
-        {
-            base.TestUniqueValuesCompression();
-        }
-
-        [Test]
-        public override void TestDateCompression()
-        {
-            base.TestDateCompression();
-        }
-
-        [Test]
-        public override void TestSingleBigValueCompression()
-        {
-            base.TestSingleBigValueCompression();
-        }
-
-        #endregion
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
index 0f35370..938ae52 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
@@ -36,67 +36,5 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
index 19cd845..cd6f9f2 100644
--- a/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
@@ -36,68 +36,5 @@ namespace Lucene.Net.Codecs.Pulsing
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
index d1c5f29..c374053 100644
--- a/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
@@ -37,67 +37,5 @@ namespace Lucene.Net.Codecs.Sep
                 return codec;
             }
         }
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
index bdd6d82..497e26f 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
@@ -42,505 +42,5 @@ namespace Lucene.Net.Codecs.SimpleText
                 return codec;
             }
         }
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
index 96e6cb8..a8cb997 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
@@ -34,68 +34,5 @@ namespace Lucene.Net.Codecs.SimpleText
                 return codec;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
index 1d3ae31..5dab469 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
@@ -31,93 +31,5 @@ namespace Lucene.Net.Codecs.SimpleText
                 return new SimpleTextCodec();
             }
         }
-
-        #region BaseStoredFieldsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestRandomStoredFields()
-        {
-            base.TestRandomStoredFields();
-        }
-
-        [Test]
-        // LUCENE-1727: make sure doc fields are stored in order
-        public override void TestStoredFieldsOrder()
-        {
-            base.TestStoredFieldsOrder();
-        }
-
-        [Test]
-        // LUCENE-1219
-        public override void TestBinaryFieldOffsetLength()
-        {
-            base.TestBinaryFieldOffsetLength();
-        }
-
-        [Test]
-        public override void TestNumericField()
-        {
-            base.TestNumericField();
-        }
-
-        [Test]
-        public override void TestIndexedBit()
-        {
-            base.TestIndexedBit();
-        }
-
-        [Test]
-        public override void TestReadSkip()
-        {
-            base.TestReadSkip();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestEmptyDocs()
-        {
-            base.TestEmptyDocs();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestConcurrentReads()
-        {
-            base.TestConcurrentReads();
-        }
-
-        [Test]
-        public override void TestWriteReadMerge()
-        {
-            base.TestWriteReadMerge();
-        }
-
-        [Test, LongRunningTest]
-        public override void TestBigDocuments()
-        {
-            base.TestBigDocuments();
-        }
-
-        [Test]
-        public override void TestBulkMergeWithDeletes()
-        {
-            base.TestBulkMergeWithDeletes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
index 527deea..a5fe4c5 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
@@ -30,71 +30,5 @@ namespace Lucene.Net.Codecs.SimpleText
                 return new SimpleTextCodec();
             }
         }
-
-        #region BaseTermVectorsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        // only one doc with vectors
-        public override void TestRareVectors()
-        {
-            base.TestRareVectors();
-        }
-
-        [Test]
-        public override void TestHighFreqs()
-        {
-            base.TestHighFreqs();
-        }
-
-        [Test]
-        public override void TestLotsOfFields()
-        {
-            base.TestLotsOfFields();
-        }
-
-        [Test, Timeout(300000)]
-        // different options for the same field
-        public override void TestMixedOptions()
-        {
-            base.TestMixedOptions();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestMerge()
-        {
-            base.TestMerge();
-        }
-
-        [Test]
-        // run random tests from different threads to make sure the per-thread clones
-        // don't share mutable data
-        public override void TestClone()
-        {
-            base.TestClone();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs b/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
index fdc0e95..164f275 100644
--- a/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
+++ b/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
@@ -87,61 +87,5 @@ namespace Lucene.Net.Index.Sorter
             reader = SlowCompositeReaderWrapper.Wrap(DirectoryReader.Open(dir));
             assertFalse("index should not have deletions", reader.HasDeletions);
         }
-
-
-        #region SorterTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestBinaryDocValuesField()
-        {
-            base.TestBinaryDocValuesField();
-        }
-
-        [Test]
-        public override void TestDocsAndPositionsEnum()
-        {
-            base.TestDocsAndPositionsEnum();
-        }
-
-        [Test]
-        public override void TestDocsEnum()
-        {
-            base.TestDocsEnum();
-        }
-
-        [Test]
-        public override void TestNormValues()
-        {
-            base.TestNormValues();
-        }
-
-        [Test]
-        public override void TestNumericDocValuesField()
-        {
-            base.TestNumericDocValuesField();
-        }
-
-        [Test]
-        public override void TestSortedDocValuesField()
-        {
-            base.TestSortedDocValuesField();
-        }
-
-        [Test]
-        public override void TestSortedSetDocValuesField()
-        {
-            base.TestSortedSetDocValuesField();
-        }
-
-        [Test]
-        public override void TestTermVectors()
-        {
-            base.TestTermVectors();
-        }
-
-        #endregion
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs b/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
index 99623ad..2cff135 100644
--- a/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
+++ b/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
@@ -230,7 +230,7 @@ namespace Lucene.Net.Index.Sorter
             dir.Dispose();
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestBinaryDocValuesField()
         {
             BinaryDocValues dv = reader.GetBinaryDocValues(BINARY_DV_FIELD);
@@ -242,7 +242,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestDocsAndPositionsEnum()
         {
             TermsEnum termsEnum = reader.Terms(DOC_POSITIONS_FIELD).Iterator(null);
@@ -322,7 +322,7 @@ namespace Lucene.Net.Index.Sorter
             return bits;
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestDocsEnum()
         {
             Bits mappedLiveDocs = RandomLiveDocs(reader.MaxDoc);
@@ -369,7 +369,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestNormValues()
         {
             NumericDocValues dv = reader.GetNormValues(NORMS_FIELD);
@@ -380,7 +380,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestNumericDocValuesField()
         {
             NumericDocValues dv = reader.GetNumericDocValues(NUMERIC_DV_FIELD);
@@ -391,7 +391,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedDocValuesField()
         {
             SortedDocValues dv = reader.GetSortedDocValues(SORTED_DV_FIELD);
@@ -404,7 +404,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestSortedSetDocValuesField()
         {
             AssumeTrue("default codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -423,7 +423,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTermVectors()
         {
             int maxDoc = reader.MaxDoc;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs b/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
index 93b234a..cb2b38e 100644
--- a/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
+++ b/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
@@ -79,61 +79,5 @@ namespace Lucene.Net.Index.Sorter
                 assertEquals("Cannot sort an index with a Sort that refers to the relevance score", e.Message);
             }
         }
-
-
-        #region SorterTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestBinaryDocValuesField()
-        {
-            base.TestBinaryDocValuesField();
-        }
-
-        [Test]
-        public override void TestDocsAndPositionsEnum()
-        {
-            base.TestDocsAndPositionsEnum();
-        }
-
-        [Test]
-        public override void TestDocsEnum()
-        {
-            base.TestDocsEnum();
-        }
-
-        [Test]
-        public override void TestNormValues()
-        {
-            base.TestNormValues();
-        }
-
-        [Test]
-        public override void TestNumericDocValuesField()
-        {
-            base.TestNumericDocValuesField();
-        }
-
-        [Test]
-        public override void TestSortedDocValuesField()
-        {
-            base.TestSortedDocValuesField();
-        }
-
-        [Test]
-        public override void TestSortedSetDocValuesField()
-        {
-            base.TestSortedSetDocValuesField();
-        }
-
-        [Test]
-        public override void TestTermVectors()
-        {
-            base.TestTermVectors();
-        }
-
-        #endregion
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs b/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
index 577f27b..2b71216 100644
--- a/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
@@ -551,255 +551,5 @@ namespace Lucene.Net.QueryParsers.Classic
             assertEquals(expected, qp.Parse("\"\u4e2d\u56fd\"~3^2"));
         }
 
-
-        #region QueryParserTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestCJK()
-        {
-            base.TestCJK();
-        }
-
-        [Test]
-        public override void TestCJKTerm()
-        {
-            base.TestCJKTerm();
-        }
-
-        [Test]
-        public override void TestCJKBoostedTerm()
-        {
-            base.TestCJKBoostedTerm();
-        }
-
-        [Test]
-        public override void TestCJKPhrase()
-        {
-            base.TestCJKPhrase();
-        }
-
-        [Test]
-        public override void TestCJKBoostedPhrase()
-        {
-            base.TestCJKBoostedPhrase();
-        }
-
-        [Test]
-        public override void TestCJKSloppyPhrase()
-        {
-            base.TestCJKSloppyPhrase();
-        }
-
-        [Test]
-        public override void TestAutoGeneratePhraseQueriesOn()
-        {
-            base.TestAutoGeneratePhraseQueriesOn();
-        }
-
-        [Test]
-        public override void TestSimple()
-        {
-            base.TestSimple();
-        }
-
-        [Test]
-        public override void TestOperatorVsWhitespace()
-        {
-            base.TestOperatorVsWhitespace();
-        }
-
-        [Test]
-        public override void TestPunct()
-        {
-            base.TestPunct();
-        }
-
-        [Test]
-        public override void TestSlop()
-        {
-            base.TestSlop();
-        }
-
-        [Test]
-        public override void TestNumber()
-        {
-            base.TestNumber();
-        }
-
-        [Test]
-        public override void TestWildcard()
-        {
-            base.TestWildcard();
-        }
-
-        [Test]
-        public override void TestLeadingWildcardType()
-        {
-            base.TestLeadingWildcardType();
-        }
-
-        [Test]
-        public override void TestQPA()
-        {
-            base.TestQPA();
-        }
-
-        [Test]
-        public override void TestRange()
-        {
-            base.TestRange();
-        }
-
-        [Test]
-        public override void TestRangeWithPhrase()
-        {
-            base.TestRangeWithPhrase();
-        }
-
-        [Test]
-        public override void TestDateRange()
-        {
-            base.TestDateRange();
-        }
-
-        [Test]
-        public override void TestEscaped()
-        {
-            base.TestEscaped();
-        }
-
-        [Test]
-        public override void TestEscapedVsQuestionMarkAsWildcard()
-        {
-            base.TestEscapedVsQuestionMarkAsWildcard();
-        }
-
-        [Test]
-        public override void TestQueryStringEscaping()
-        {
-            base.TestQueryStringEscaping();
-        }
-
-        [Test]
-        public override void TestTabNewlineCarriageReturn()
-        {
-            base.TestTabNewlineCarriageReturn();
-        }
-
-        [Test]
-        public override void TestSimpleDAO()
-        {
-            base.TestSimpleDAO();
-        }
-
-        [Test]
-        public override void TestBoost()
-        {
-            base.TestBoost();
-        }
-
-        [Test]
-        public override void TestException()
-        {
-            base.TestException();
-        }
-
-        [Test]
-        public override void TestBooleanQuery()
-        {
-            base.TestBooleanQuery();
-        }
-
-        [Test]
-        public override void TestPrecedence()
-        {
-            base.TestPrecedence();
-        }
-
-        [Test]
-        public override void TestEscapedWildcard()
-        {
-            base.TestEscapedWildcard();
-        }
-
-        [Test]
-        public override void TestRegexps()
-        {
-            base.TestRegexps();
-        }
-
-        [Test]
-        public override void TestStopwords()
-        {
-            base.TestStopwords();
-        }
-
-        [Test]
-        public override void TestPositionIncrement()
-        {
-            base.TestPositionIncrement();
-        }
-
-        [Test]
-        public override void TestMatchAllDocs()
-        {
-            base.TestMatchAllDocs();
-        }
-
-        // LUCENE-2002: make sure defaults for StandardAnalyzer's
-        // enableStopPositionIncr & QueryParser's enablePosIncr
-        // "match"
-        [Test]
-        public override void TestPositionIncrements()
-        {
-            base.TestPositionIncrements();
-        }
-
-        [Test]
-        public override void TestCollatedRange()
-        {
-            base.TestCollatedRange();
-        }
-
-        [Test]
-        public override void TestDistanceAsEditsParsing()
-        {
-            base.TestDistanceAsEditsParsing();
-        }
-
-        [Test]
-        public override void TestPhraseQueryToString()
-        {
-            base.TestPhraseQueryToString();
-        }
-
-        [Test]
-        public override void TestParseWildcardAndPhraseQueries()
-        {
-            base.TestParseWildcardAndPhraseQueries();
-        }
-
-        [Test]
-        public override void TestPhraseQueryPositionIncrements()
-        {
-            base.TestPhraseQueryPositionIncrements();
-        }
-
-        [Test]
-        public override void TestMatchAllQueryParsing()
-        {
-            base.TestMatchAllQueryParsing();
-        }
-
-        [Test]
-        public override void TestNestedAndClausesFoo()
-        {
-            base.TestNestedAndClausesFoo();
-        }
-
-        #endregion
     }
 }


[18/58] [abbrv] lucenenet git commit: Revert "HACK: Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context."

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs b/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
index e49ed8d..e90b365 100644
--- a/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
@@ -141,374 +141,5 @@ namespace Lucene.Net.QueryParsers.Ext
                 assertEquals("foo & bar", tquery.Term.Text());
             }
         }
-
-
-        #region TestQueryParser
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDefaultOperator()
-        {
-            base.TestDefaultOperator();
-        }
-
-        [Test]
-        public override void TestProtectedCtors()
-        {
-            base.TestProtectedCtors();
-        }
-
-        [Test]
-        public override void TestFuzzySlopeExtendability()
-        {
-            base.TestFuzzySlopeExtendability();
-        }
-
-        [Test]
-        public override void TestStarParsing()
-        {
-            base.TestStarParsing();
-        }
-
-        [Test]
-        public override void TestCustomQueryParserWildcard()
-        {
-            base.TestCustomQueryParserWildcard();
-        }
-
-        [Test]
-        public override void TestCustomQueryParserFuzzy()
-        {
-            base.TestCustomQueryParserFuzzy();
-        }
-
-        [Test]
-        public override void TestNewFieldQuery()
-        {
-            base.TestNewFieldQuery();
-        }
-
-        /// <summary>
-        /// simple synonyms test
-        /// </summary>
-        [Test]
-        public override void TestSynonyms()
-        {
-            base.TestSynonyms();
-        }
-
-        /// <summary>
-        /// forms multiphrase query
-        /// </summary>
-        [Test]
-        public override void TestSynonymsPhrase()
-        {
-            base.TestSynonymsPhrase();
-        }
-
-        /// <summary>
-        /// simple CJK synonym test
-        /// </summary>
-        [Test]
-        public override void TestCJKSynonym()
-        {
-            base.TestCJKSynonym();
-        }
-
-        /// <summary>
-        /// synonyms with default OR operator 
-        /// </summary>
-        [Test]
-        public override void TestCJKSynonymsOR()
-        {
-            base.TestCJKSynonymsOR();
-        }
-
-        /// <summary>
-        /// more complex synonyms with default OR operator
-        /// </summary>
-        [Test]
-        public override void TestCJKSynonymsOR2()
-        {
-            base.TestCJKSynonymsOR2();
-        }
-
-        /// <summary>
-        /// synonyms with default AND operator
-        /// </summary>
-        [Test]
-        public override void TestCJKSynonymsAND()
-        {
-            base.TestCJKSynonymsAND();
-        }
-
-        /// <summary>
-        /// more complex synonyms with default AND operator
-        /// </summary>
-        [Test]
-        public override void TestCJKSynonymsAND2()
-        {
-            base.TestCJKSynonymsAND2();
-        }
-
-        [Test]
-        public override void TestCJKSynonymsPhrase()
-        {
-            base.TestCJKSynonymsPhrase();
-        }
-
-        #endregion
-
-        #region QueryParserTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestCJK()
-        {
-            base.TestCJK();
-        }
-
-        [Test]
-        public override void TestCJKTerm()
-        {
-            base.TestCJKTerm();
-        }
-
-        [Test]
-        public override void TestCJKBoostedTerm()
-        {
-            base.TestCJKBoostedTerm();
-        }
-
-        [Test]
-        public override void TestCJKPhrase()
-        {
-            base.TestCJKPhrase();
-        }
-
-        [Test]
-        public override void TestCJKBoostedPhrase()
-        {
-            base.TestCJKBoostedPhrase();
-        }
-
-        [Test]
-        public override void TestCJKSloppyPhrase()
-        {
-            base.TestCJKSloppyPhrase();
-        }
-
-        [Test]
-        public override void TestAutoGeneratePhraseQueriesOn()
-        {
-            base.TestAutoGeneratePhraseQueriesOn();
-        }
-
-        [Test]
-        public override void TestSimple()
-        {
-            base.TestSimple();
-        }
-
-        [Test]
-        public override void TestOperatorVsWhitespace()
-        {
-            base.TestOperatorVsWhitespace();
-        }
-
-        [Test]
-        public override void TestPunct()
-        {
-            base.TestPunct();
-        }
-
-        [Test]
-        public override void TestSlop()
-        {
-            base.TestSlop();
-        }
-
-        [Test]
-        public override void TestNumber()
-        {
-            base.TestNumber();
-        }
-
-        [Test]
-        public override void TestWildcard()
-        {
-            base.TestWildcard();
-        }
-
-        [Test]
-        public override void TestLeadingWildcardType()
-        {
-            base.TestLeadingWildcardType();
-        }
-
-        [Test]
-        public override void TestQPA()
-        {
-            base.TestQPA();
-        }
-
-        [Test]
-        public override void TestRange()
-        {
-            base.TestRange();
-        }
-
-        [Test]
-        public override void TestRangeWithPhrase()
-        {
-            base.TestRangeWithPhrase();
-        }
-
-        [Test]
-        public override void TestDateRange()
-        {
-            base.TestDateRange();
-        }
-
-        [Test]
-        public override void TestEscaped()
-        {
-            base.TestEscaped();
-        }
-
-        [Test]
-        public override void TestEscapedVsQuestionMarkAsWildcard()
-        {
-            base.TestEscapedVsQuestionMarkAsWildcard();
-        }
-
-        [Test]
-        public override void TestQueryStringEscaping()
-        {
-            base.TestQueryStringEscaping();
-        }
-
-        [Test]
-        public override void TestTabNewlineCarriageReturn()
-        {
-            base.TestTabNewlineCarriageReturn();
-        }
-
-        [Test]
-        public override void TestSimpleDAO()
-        {
-            base.TestSimpleDAO();
-        }
-
-        [Test]
-        public override void TestBoost()
-        {
-            base.TestBoost();
-        }
-
-        [Test]
-        public override void TestException()
-        {
-            base.TestException();
-        }
-
-        [Test]
-        public override void TestBooleanQuery()
-        {
-            base.TestBooleanQuery();
-        }
-
-        [Test]
-        public override void TestPrecedence()
-        {
-            base.TestPrecedence();
-        }
-
-        [Test]
-        public override void TestEscapedWildcard()
-        {
-            base.TestEscapedWildcard();
-        }
-
-        [Test]
-        public override void TestRegexps()
-        {
-            base.TestRegexps();
-        }
-
-        [Test]
-        public override void TestStopwords()
-        {
-            base.TestStopwords();
-        }
-
-        [Test]
-        public override void TestPositionIncrement()
-        {
-            base.TestPositionIncrement();
-        }
-
-        [Test]
-        public override void TestMatchAllDocs()
-        {
-            base.TestMatchAllDocs();
-        }
-
-        // LUCENE-2002: make sure defaults for StandardAnalyzer's
-        // enableStopPositionIncr & QueryParser's enablePosIncr
-        // "match"
-        [Test]
-        public override void TestPositionIncrements()
-        {
-            base.TestPositionIncrements();
-        }
-
-        [Test]
-        public override void TestCollatedRange()
-        {
-            base.TestCollatedRange();
-        }
-
-        [Test]
-        public override void TestDistanceAsEditsParsing()
-        {
-            base.TestDistanceAsEditsParsing();
-        }
-
-        [Test]
-        public override void TestPhraseQueryToString()
-        {
-            base.TestPhraseQueryToString();
-        }
-
-        [Test]
-        public override void TestParseWildcardAndPhraseQueries()
-        {
-            base.TestParseWildcardAndPhraseQueries();
-        }
-
-        [Test]
-        public override void TestPhraseQueryPositionIncrements()
-        {
-            base.TestPhraseQueryPositionIncrements();
-        }
-
-        [Test]
-        public override void TestMatchAllQueryParsing()
-        {
-            base.TestMatchAllQueryParsing();
-        }
-
-        [Test]
-        public override void TestNestedAndClausesFoo()
-        {
-            base.TestNestedAndClausesFoo();
-        }
-
-        #endregion
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
index 9dcfcde..37f00e2 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
@@ -88,7 +88,7 @@ namespace Lucene.Net.Codecs.Compressing
             return Arrays.CopyOfRange(bytes.Bytes, bytes.Offset, bytes.Offset + bytes.Length);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestDecompress()
         {
             int iterations = AtLeast(10);
@@ -103,7 +103,7 @@ namespace Lucene.Net.Codecs.Compressing
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestPartialDecompress()
         {
             int iterations = AtLeast(10);
@@ -139,19 +139,19 @@ namespace Lucene.Net.Codecs.Compressing
             return compressed;
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestEmptySequence()
         {
             Test(new byte[0]);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestShortSequence()
         {
             Test(new[] { (byte)Random().Next(256) });
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestIncompressible()
         {
             var decompressed = new byte[RandomInts.NextIntBetween(Random(), 20, 256)];
@@ -162,7 +162,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestConstant()
         {
             var decompressed = new byte[TestUtil.NextInt(Random(), 1, 10000)];
@@ -170,7 +170,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestLUCENE5201()
         {
             sbyte[] data = { 14, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 72, 14, 72, 14, 85, 3, 72, 14, 72, 14, 72, 14, 72, 14, 72, 14, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 50, 64, 0, 46, -1, 0, 0, 0, 29, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 50, 64, 0, 47, -105, 0, 0, 0, 30, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, -97, 6, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68
 , -113, 0, 120, 64, 0, 48, 4, 0, 0, 0, 31, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 24, 32, 34, 124, 0, 120, 64, 0, 48, 80, 0, 0, 0, 31, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 
 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 7
 2, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 50, 64, 0, 49, 20, 0, 0, 0, 32, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 50, 64, 0, 50, 53, 0, 0, 0, 34, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0
 , 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 50, 64, 0, 51, 85, 0, 0, 0, 36, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, -97, 5, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 50, -64, 0, 51, -45, 0, 0, 0, 37, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -9
 7, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 120, 64, 0, 52, -88, 0, 0, 0, 39, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, -19, -24, -101, -35 };

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
index 334ae8d..feb57d0 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
@@ -88,7 +88,7 @@ namespace Lucene.Net.Codecs.Compressing
             return compressed;
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestShortLiteralsAndMatchs()
         {
             // literals and matchs lengths <= 15
@@ -96,7 +96,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestLongMatchs()
         {
             // match length >= 20
@@ -108,7 +108,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestLongLiterals()
         {
             // long literals (length >= 16) which are not the last literals
@@ -120,7 +120,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestMatchRightBeforeLastLiterals()
         {
             Test(new byte[] { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 5 });

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
index 998b942..acdf73c 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
@@ -100,94 +100,5 @@ namespace Lucene.Net.Codecs.Compressing
                 this.OuterInstance = outerInstance;
             }
         }
-
-
-        #region BaseStoredFieldsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestRandomStoredFields()
-        {
-            base.TestRandomStoredFields();
-        }
-
-        [Test]
-        // LUCENE-1727: make sure doc fields are stored in order
-        public override void TestStoredFieldsOrder()
-        {
-            base.TestStoredFieldsOrder();
-        }
-
-        [Test]
-        // LUCENE-1219
-        public override void TestBinaryFieldOffsetLength()
-        {
-            base.TestBinaryFieldOffsetLength();
-        }
-
-        [Test]
-        public override void TestNumericField()
-        {
-            base.TestNumericField();
-        }
-
-        [Test]
-        public override void TestIndexedBit()
-        {
-            base.TestIndexedBit();
-        }
-
-        [Test]
-        public override void TestReadSkip()
-        {
-            base.TestReadSkip();
-        }
-
-        [Test]
-        public override void TestEmptyDocs()
-        {
-            base.TestEmptyDocs();
-        }
-
-        [Test]
-        public override void TestConcurrentReads()
-        {
-            base.TestConcurrentReads();
-        }
-
-        [Test]
-        public override void TestWriteReadMerge()
-        {
-            base.TestWriteReadMerge();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestBigDocuments()
-        {
-            base.TestBigDocuments();
-        }
-
-        [Test]
-        public override void TestBulkMergeWithDeletes()
-        {
-            base.TestBulkMergeWithDeletes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
index 709af74..90b06cf 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
@@ -84,72 +84,5 @@ namespace Lucene.Net.Codecs.Compressing
             iw.Dispose();
             dir.Dispose();
         }
-
-
-        #region BaseTermVectorsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        // only one doc with vectors
-        public override void TestRareVectors()
-        {
-            base.TestRareVectors();
-        }
-
-        [Test]
-        public override void TestHighFreqs()
-        {
-            base.TestHighFreqs();
-        }
-
-        [Test]
-        public override void TestLotsOfFields()
-        {
-            base.TestLotsOfFields();
-        }
-
-        [Test]
-        // different options for the same field
-        public override void TestMixedOptions()
-        {
-            base.TestMixedOptions();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test, Timeout(30000)]
-        public override void TestMerge()
-        {
-            base.TestMerge();
-        }
-
-        [Test]
-        // run random tests from different threads to make sure the per-thread clones
-        // don't share mutable data
-        public override void TestClone()
-        {
-            base.TestClone();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
index 6a74a51..dd7d708 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
@@ -28,86 +28,5 @@ namespace Lucene.Net.Codecs.Compressing
             base.SetUp();
             Mode = CompressionMode.FAST;
         }
-
-
-        #region AbstractTestLZ4CompressionMode
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestShortLiteralsAndMatchs()
-        {
-            base.TestShortLiteralsAndMatchs();
-        }
-
-        [Test]
-        public override void TestLongMatchs()
-        {
-            base.TestLongMatchs();
-        }
-
-        [Test]
-        public override void TestLongLiterals()
-        {
-            base.TestLongLiterals();
-        }
-
-        [Test]
-        public override void TestMatchRightBeforeLastLiterals()
-        {
-            base.TestMatchRightBeforeLastLiterals();
-        }
-
-        #endregion
-
-        #region AbstractTestCompressionMode
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDecompress()
-        {
-            base.TestDecompress();
-        }
-
-        [Test]
-        public override void TestPartialDecompress()
-        {
-            base.TestPartialDecompress();
-        }
-
-        [Test]
-        public override void TestEmptySequence()
-        {
-            base.TestEmptySequence();
-        }
-
-        [Test]
-        public override void TestShortSequence()
-        {
-            base.TestShortSequence();
-        }
-
-        [Test]
-        public override void TestIncompressible()
-        {
-            base.TestIncompressible();
-        }
-
-        [Test]
-        public override void TestConstant()
-        {
-            base.TestConstant();
-        }
-
-        [Test]
-        public override void TestLUCENE5201()
-        {
-            base.TestLUCENE5201();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
index b90a582..d7fc0b0 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
@@ -38,86 +38,5 @@ namespace Lucene.Net.Codecs.Compressing
             Assert.IsTrue(compressed.Length <= compressed2.Length);
             return compressed;
         }
-
-
-        #region AbstractTestLZ4CompressionMode
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestShortLiteralsAndMatchs()
-        {
-            base.TestShortLiteralsAndMatchs();
-        }
-
-        [Test]
-        public override void TestLongMatchs()
-        {
-            base.TestLongMatchs();
-        }
-
-        [Test]
-        public override void TestLongLiterals()
-        {
-            base.TestLongLiterals();
-        }
-
-        [Test]
-        public override void TestMatchRightBeforeLastLiterals()
-        {
-            base.TestMatchRightBeforeLastLiterals();
-        }
-
-        #endregion
-
-        #region AbstractTestCompressionMode
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDecompress()
-        {
-            base.TestDecompress();
-        }
-
-        [Test]
-        public override void TestPartialDecompress()
-        {
-            base.TestPartialDecompress();
-        }
-
-        [Test]
-        public override void TestEmptySequence()
-        {
-            base.TestEmptySequence();
-        }
-
-        [Test]
-        public override void TestShortSequence()
-        {
-            base.TestShortSequence();
-        }
-
-        [Test]
-        public override void TestIncompressible()
-        {
-            base.TestIncompressible();
-        }
-
-        [Test]
-        public override void TestConstant()
-        {
-            base.TestConstant();
-        }
-
-        [Test]
-        public override void TestLUCENE5201()
-        {
-            base.TestLUCENE5201();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
index 679d1f0..eebcda1 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
@@ -28,55 +28,5 @@ namespace Lucene.Net.Codecs.Compressing
             base.SetUp();
             Mode = CompressionMode.HIGH_COMPRESSION;
         }
-
-
-        #region AbstractTestCompressionMode
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDecompress()
-        {
-            base.TestDecompress();
-        }
-
-        [Test]
-        public override void TestPartialDecompress()
-        {
-            base.TestPartialDecompress();
-        }
-
-        [Test]
-        public override void TestEmptySequence()
-        {
-            base.TestEmptySequence();
-        }
-
-        [Test]
-        public override void TestShortSequence()
-        {
-            base.TestShortSequence();
-        }
-
-        [Test]
-        public override void TestIncompressible()
-        {
-            base.TestIncompressible();
-        }
-
-        [Test]
-        public override void TestConstant()
-        {
-            base.TestConstant();
-        }
-
-        [Test]
-        public override void TestLUCENE5201()
-        {
-            base.TestLUCENE5201();
-        }
-        #endregion
-
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
index 0ab9a7b..cf1bafc 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
@@ -42,68 +42,5 @@ namespace Lucene.Net.Codecs.Lucene3x
                 return Codec_Renamed;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
index d3d0889..b28f86a 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
@@ -52,89 +52,5 @@ namespace Lucene.Net.Codecs.Lucene3x
             // for 3.x: we currently cannot take an index with existing 4.x segments
             // and merge into newly formed 3.x segments.
         }
-
-
-
-        #region BaseStoredFieldsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestRandomStoredFields()
-        {
-            base.TestRandomStoredFields();
-        }
-
-        [Test]
-        // LUCENE-1727: make sure doc fields are stored in order
-        public override void TestStoredFieldsOrder()
-        {
-            base.TestStoredFieldsOrder();
-        }
-
-        [Test]
-        // LUCENE-1219
-        public override void TestBinaryFieldOffsetLength()
-        {
-            base.TestBinaryFieldOffsetLength();
-        }
-
-        [Test]
-        public override void TestNumericField()
-        {
-            base.TestNumericField();
-        }
-
-        [Test]
-        public override void TestIndexedBit()
-        {
-            base.TestIndexedBit();
-        }
-
-        [Test]
-        public override void TestReadSkip()
-        {
-            base.TestReadSkip();
-        }
-
-        [Test]
-        public override void TestEmptyDocs()
-        {
-            base.TestEmptyDocs();
-        }
-
-        [Test]
-        public override void TestConcurrentReads()
-        {
-            base.TestConcurrentReads();
-        }
-
-        [Test, Timeout(120000)]
-        public override void TestBigDocuments()
-        {
-            base.TestBigDocuments();
-        }
-
-        [Test]
-        public override void TestBulkMergeWithDeletes()
-        {
-            base.TestBulkMergeWithDeletes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
index 5756752..1cf090b 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
@@ -46,72 +46,5 @@ namespace Lucene.Net.Codecs.Lucene3x
         {
             return ValidOptions(Options.NONE, Options.POSITIONS_AND_OFFSETS);
         }
-
-
-        #region BaseTermVectorsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        // only one doc with vectors
-        public override void TestRareVectors()
-        {
-            base.TestRareVectors();
-        }
-
-        [Test]
-        public override void TestHighFreqs()
-        {
-            base.TestHighFreqs();
-        }
-
-        [Test]
-        public override void TestLotsOfFields()
-        {
-            base.TestLotsOfFields();
-        }
-
-        [Test, Timeout(300000)]
-        // different options for the same field
-        public override void TestMixedOptions()
-        {
-            base.TestMixedOptions();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestMerge()
-        {
-            base.TestMerge();
-        }
-
-        [Test]
-        // run random tests from different threads to make sure the per-thread clones
-        // don't share mutable data
-        public override void TestClone()
-        {
-            base.TestClone();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
index 3686767..9ee39e7 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
@@ -50,506 +50,5 @@ namespace Lucene.Net.Codecs.Lucene40
         {
             return false;
         }
-
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
index 0d3666d..c7f7f07 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
@@ -44,68 +44,5 @@ namespace Lucene.Net.Codecs.Lucene40
                 return new Lucene40RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
index 4e3bebf..4e57234 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
@@ -41,94 +41,5 @@ namespace Lucene.Net.Codecs.Lucene40
                 return new Lucene40RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
-
-
-        #region BaseStoredFieldsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestRandomStoredFields()
-        {
-            base.TestRandomStoredFields();
-        }
-
-        [Test]
-        // LUCENE-1727: make sure doc fields are stored in order
-        public override void TestStoredFieldsOrder()
-        {
-            base.TestStoredFieldsOrder();
-        }
-
-        [Test]
-        // LUCENE-1219
-        public override void TestBinaryFieldOffsetLength()
-        {
-            base.TestBinaryFieldOffsetLength();
-        }
-
-        [Test]
-        public override void TestNumericField()
-        {
-            base.TestNumericField();
-        }
-
-        [Test]
-        public override void TestIndexedBit()
-        {
-            base.TestIndexedBit();
-        }
-
-        [Test]
-        public override void TestReadSkip()
-        {
-            base.TestReadSkip();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestEmptyDocs()
-        {
-            base.TestEmptyDocs();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestConcurrentReads()
-        {
-            base.TestConcurrentReads();
-        }
-
-        [Test]
-        public override void TestWriteReadMerge()
-        {
-            base.TestWriteReadMerge();
-        }
-
-        [Test, Timeout(80000)]
-        public override void TestBigDocuments()
-        {
-            base.TestBigDocuments();
-        }
-
-        [Test]
-        public override void TestBulkMergeWithDeletes()
-        {
-            base.TestBulkMergeWithDeletes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
index 9a6e544..342d7ce 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
@@ -41,72 +41,5 @@ namespace Lucene.Net.Codecs.Lucene40
                 return new Lucene40RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
-
-
-        #region BaseTermVectorsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        // only one doc with vectors
-        public override void TestRareVectors()
-        {
-            base.TestRareVectors();
-        }
-
-        [Test]
-        public override void TestHighFreqs()
-        {
-            base.TestHighFreqs();
-        }
-
-        [Test]
-        public override void TestLotsOfFields()
-        {
-            base.TestLotsOfFields();
-        }
-
-        [Test, Timeout(300000)]
-        // different options for the same field
-        public override void TestMixedOptions()
-        {
-            base.TestMixedOptions();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestMerge()
-        {
-            base.TestMerge();
-        }
-
-        [Test]
-        // run random tests from different threads to make sure the per-thread clones
-        // don't share mutable data
-        public override void TestClone()
-        {
-            base.TestClone();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
index fb309a5..201eaf6 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Codecs.Lucene41
 {
     /*
@@ -36,68 +34,5 @@ namespace Lucene.Net.Codecs.Lucene41
                 return Codec_Renamed;
             }
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
index bcd5a49..4259478 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
@@ -40,94 +40,5 @@ namespace Lucene.Net.Codecs.Lucene41
                 return new Lucene41RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
-
-
-        #region BaseStoredFieldsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestRandomStoredFields()
-        {
-            base.TestRandomStoredFields();
-        }
-
-        [Test]
-        // LUCENE-1727: make sure doc fields are stored in order
-        public override void TestStoredFieldsOrder()
-        {
-            base.TestStoredFieldsOrder();
-        }
-
-        [Test]
-        // LUCENE-1219
-        public override void TestBinaryFieldOffsetLength()
-        {
-            base.TestBinaryFieldOffsetLength();
-        }
-
-        [Test]
-        public override void TestNumericField()
-        {
-            base.TestNumericField();
-        }
-
-        [Test]
-        public override void TestIndexedBit()
-        {
-            base.TestIndexedBit();
-        }
-
-        [Test]
-        public override void TestReadSkip()
-        {
-            base.TestReadSkip();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestEmptyDocs()
-        {
-            base.TestEmptyDocs();
-        }
-
-        [Test, Timeout(300000)]
-        public override void TestConcurrentReads()
-        {
-            base.TestConcurrentReads();
-        }
-
-        [Test]
-        public override void TestWriteReadMerge()
-        {
-            base.TestWriteReadMerge();
-        }
-
-        [Test, Timeout(120000)]
-        public override void TestBigDocuments()
-        {
-            base.TestBigDocuments();
-        }
-
-        [Test]
-        public override void TestBulkMergeWithDeletes()
-        {
-            base.TestBulkMergeWithDeletes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
index 598f373..7f4438b 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
@@ -51,531 +51,5 @@ namespace Lucene.Net.Codecs.Lucene42
         {
             return false;
         }
-
-
-        #region BaseCompressingDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestUniqueValuesCompression()
-        {
-            base.TestUniqueValuesCompression();
-        }
-
-        [Test]
-        public override void TestDateCompression()
-        {
-            base.TestDateCompression();
-        }
-
-        [Test]
-        public override void TestSingleBigValueCompression()
-        {
-            base.TestSingleBigValueCompression();
-        }
-
-        #endregion
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file


[50/58] [abbrv] lucenenet git commit: Cleaned up usings in Grouping.

Posted by ni...@apache.org.
Cleaned up usings in Grouping.


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

Branch: refs/heads/grouping
Commit: 3881180835b2c605b0fc587c54f2676c7f521f1e
Parents: 5c9a388
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 23:31:51 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:20 2016 +0700

----------------------------------------------------------------------
 .../AbstractAllGroupHeadsCollector.cs           |  8 +----
 .../AbstractDistinctValuesCollector.cs          |  7 +----
 .../AbstractGroupFacetCollector.cs              |  7 +----
 src/Lucene.Net.Grouping/CollectedSearchGroup.cs |  8 +----
 .../Function/FunctionAllGroupHeadsCollector.cs  |  5 ---
 .../Term/TermAllGroupHeadsCollector.cs          |  5 ---
 .../Term/TermAllGroupsCollector.cs              |  4 ---
 .../Term/TermFirstPassGroupingCollector.cs      |  1 -
 .../Term/TermGroupFacetCollector.cs             |  5 ---
 .../AbstractGroupingTestCase.cs                 |  4 ---
 .../AllGroupHeadsCollectorTest.cs               | 32 +++++++++-----------
 .../AllGroupsCollectorTest.cs                   |  9 ++----
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs   |  1 -
 13 files changed, 20 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
index 4d3b66f..279805e 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -1,11 +1,5 @@
-\ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
-using Lucene.Net.Util;
-using System;
+\ufeffusing Lucene.Net.Util;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
index 5c3e624..f832b1b 100644
--- a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
@@ -1,9 +1,4 @@
-\ufeffusing Lucene.Net.Search;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+\ufeffusing System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
index 920e6d3..9a079e8 100644
--- a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
@@ -1,11 +1,6 @@
-\ufeffusing Lucene.Net.Search;
-using Lucene.Net.Support;
+\ufeffusing Lucene.Net.Support;
 using Lucene.Net.Util;
-using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
index 50b5bd7..51a905f 100644
--- a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
+++ b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
@@ -1,10 +1,4 @@
-\ufeffusing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Lucene.Net.Search.Grouping
+\ufeffnamespace Lucene.Net.Search.Grouping
 {
     /// <summary>
     /// Expert: representation of a group in {@link AbstractFirstPassGroupingCollector},

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
index f0410d2..70aa484 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
@@ -1,13 +1,8 @@
 \ufeffusing Lucene.Net.Index;
 using Lucene.Net.Queries.Function;
-using Lucene.Net.Search;
 using Lucene.Net.Util.Mutable;
-using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping.Function
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
index 4aa9615..8b5776e 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
@@ -1,12 +1,7 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Support;
 using Lucene.Net.Util;
-using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
index ef33aa5..953bb82 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupsCollector.cs
@@ -1,11 +1,7 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
index 17003ba..9f61ae7 100644
--- a/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermFirstPassGroupingCollector.cs
@@ -1,5 +1,4 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Util;
 
 namespace Lucene.Net.Search.Grouping.Terms

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs b/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
index 08fbb70..e694ef2 100644
--- a/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermGroupFacetCollector.cs
@@ -1,12 +1,7 @@
 \ufeffusing Lucene.Net.Index;
-using Lucene.Net.Search;
 using Lucene.Net.Util;
-using System;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping.Terms
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
index d4cd062..74a926a 100644
--- a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
+++ b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
@@ -1,9 +1,5 @@
 \ufeffusing Lucene.Net.Util;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index 2d8e8fe..0f1ddb2 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -1,30 +1,26 @@
 \ufeffusing Lucene.Net.Analysis;
 using Lucene.Net.Documents;
-using Lucene.Net.Search.Grouping.Function;
 using Lucene.Net.Index;
 using Lucene.Net.Queries.Function;
 using Lucene.Net.Queries.Function.ValueSources;
-using Lucene.Net.Search;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Search.Grouping.Terms;
 using Lucene.Net.Store;
+using Lucene.Net.Support;
 using Lucene.Net.Util;
 using NUnit.Framework;
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Globalization;
-using System.Linq;
 using System.Text;
-using System.Threading.Tasks;
-using static Lucene.Net.Index.FieldInfo;
-using Lucene.Net.Search.Grouping.Terms;
-using System.Collections;
-using Lucene.Net.Support;
 
 namespace Lucene.Net.Search.Grouping
 {
     public class AllGroupHeadsCollectorTest : LuceneTestCase
     {
-        private static readonly DocValuesType_e[] vts = new DocValuesType_e[]{
-            DocValuesType_e.BINARY, DocValuesType_e.SORTED
+        private static readonly FieldInfo.DocValuesType_e[] vts = new FieldInfo.DocValuesType_e[]{
+            FieldInfo.DocValuesType_e.BINARY, FieldInfo.DocValuesType_e.SORTED
         };
 
         [Test]
@@ -38,7 +34,7 @@ namespace Lucene.Net.Search.Grouping
             NewIndexWriterConfig(TEST_VERSION_CURRENT,
                 new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
             bool canUseIDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
-            DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
+            FieldInfo.DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
 
             // 0
             Document doc = new Document();
@@ -203,7 +199,7 @@ namespace Lucene.Net.Search.Grouping
                         new MockAnalyzer(Random())));
                 bool preFlex = "Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
                 bool canUseIDV = !preFlex;
-                DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
+                FieldInfo.DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
 
                 Document doc = new Document();
                 Document docNoGroup = new Document();
@@ -214,10 +210,10 @@ namespace Lucene.Net.Search.Grouping
                 {
                     switch (valueType)
                     {
-                        case DocValuesType_e.BINARY:
+                        case FieldInfo.DocValuesType_e.BINARY:
                             valuesField = new BinaryDocValuesField("group_dv", new BytesRef());
                             break;
-                        case DocValuesType_e.SORTED:
+                        case FieldInfo.DocValuesType_e.SORTED:
                             valuesField = new SortedDocValuesField("group_dv", new BytesRef());
                             break;
                         default:
@@ -601,7 +597,7 @@ namespace Lucene.Net.Search.Grouping
             return new ComparatorAnonymousHelper(this, sortFields, sortByScoreOnly, fieldIdToDocID);
         }
 
-        private AbstractAllGroupHeadsCollector CreateRandomCollector(string groupField, Sort sortWithinGroup, bool canUseIDV, DocValuesType_e valueType)
+        private AbstractAllGroupHeadsCollector CreateRandomCollector(string groupField, Sort sortWithinGroup, bool canUseIDV, FieldInfo.DocValuesType_e valueType)
         {
             AbstractAllGroupHeadsCollector collector;
             if (Random().nextBoolean())
@@ -622,7 +618,7 @@ namespace Lucene.Net.Search.Grouping
             return collector;
         }
 
-        private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV, DocValuesType_e valueType)
+        private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV, FieldInfo.DocValuesType_e valueType)
         {
             doc.Add(new TextField(groupField, value, Field.Store.YES));
             if (canUseIDV)
@@ -630,10 +626,10 @@ namespace Lucene.Net.Search.Grouping
                 Field valuesField = null;
                 switch (valueType)
                 {
-                    case DocValuesType_e.BINARY:
+                    case FieldInfo.DocValuesType_e.BINARY:
                         valuesField = new BinaryDocValuesField(groupField + "_dv", new BytesRef(value));
                         break;
-                    case DocValuesType_e.SORTED:
+                    case FieldInfo.DocValuesType_e.SORTED:
                         valuesField = new SortedDocValuesField(groupField + "_dv", new BytesRef(value));
                         break;
                     default:

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
index 1efd4b5..2d42c43 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
@@ -1,20 +1,15 @@
 \ufeffusing Lucene.Net.Analysis;
 using Lucene.Net.Documents;
-using Lucene.Net.Search.Grouping.Function;
 using Lucene.Net.Index;
 using Lucene.Net.Queries.Function;
 using Lucene.Net.Queries.Function.ValueSources;
-using Lucene.Net.Search;
+using Lucene.Net.Search.Grouping.Function;
+using Lucene.Net.Search.Grouping.Terms;
 using Lucene.Net.Store;
 using Lucene.Net.Util;
 using NUnit.Framework;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Collections;
-using Lucene.Net.Search.Grouping.Terms;
 
 namespace Lucene.Net.Search.Grouping
 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/38811808/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index dc4743e..6098887 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -15,7 +15,6 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {


[24/58] [abbrv] lucenenet git commit: HACK: (3rd) Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context.

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
index ace0574..889f963 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectDocValuesFormat.cs
@@ -35,5 +35,506 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
index 990e29c..0bfd3d7 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestDirectPostingsFormat.cs
@@ -36,5 +36,68 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
index 6f30a01..910584c 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPostingsFormat.cs
@@ -35,5 +35,68 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
index ddb99c6..eb47d6c 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTOrdPulsing41PostingsFormat.cs
@@ -35,5 +35,68 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
index cac7e77..7e094fd 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPostingsFormat.cs
@@ -35,5 +35,68 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
index e9beed4..13afde6 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestFSTPulsing41PostingsFormat.cs
@@ -35,5 +35,68 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
index 4f65807..33895b1 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryDocValuesFormat.cs
@@ -40,5 +40,531 @@ namespace Lucene.Net.Codecs.Memory
         {
             return false;
         }
+
+
+        #region BaseCompressingDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestUniqueValuesCompression()
+        {
+            base.TestUniqueValuesCompression();
+        }
+
+        [Test]
+        public override void TestDateCompression()
+        {
+            base.TestDateCompression();
+        }
+
+        [Test]
+        public override void TestSingleBigValueCompression()
+        {
+            base.TestSingleBigValueCompression();
+        }
+
+        #endregion
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
index 938ae52..0f35370 100644
--- a/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Memory/TestMemoryPostingsFormat.cs
@@ -36,5 +36,67 @@ namespace Lucene.Net.Codecs.Memory
                 return codec;
             }
         }
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
index cd6f9f2..19cd845 100644
--- a/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Pulsing/TestPulsingPostingsFormat.cs
@@ -36,5 +36,68 @@ namespace Lucene.Net.Codecs.Pulsing
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
index c374053..d1c5f29 100644
--- a/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/Sep/TestSepPostingsFormat.cs
@@ -37,5 +37,67 @@ namespace Lucene.Net.Codecs.Sep
                 return codec;
             }
         }
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
index 497e26f..bdd6d82 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextDocValuesFormat.cs
@@ -42,5 +42,505 @@ namespace Lucene.Net.Codecs.SimpleText
                 return codec;
             }
         }
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
index a8cb997..96e6cb8 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextPostingsFormat.cs
@@ -34,5 +34,68 @@ namespace Lucene.Net.Codecs.SimpleText
                 return codec;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
index 5dab469..1d3ae31 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextStoredFieldsFormat.cs
@@ -31,5 +31,93 @@ namespace Lucene.Net.Codecs.SimpleText
                 return new SimpleTextCodec();
             }
         }
+
+        #region BaseStoredFieldsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestRandomStoredFields()
+        {
+            base.TestRandomStoredFields();
+        }
+
+        [Test]
+        // LUCENE-1727: make sure doc fields are stored in order
+        public override void TestStoredFieldsOrder()
+        {
+            base.TestStoredFieldsOrder();
+        }
+
+        [Test]
+        // LUCENE-1219
+        public override void TestBinaryFieldOffsetLength()
+        {
+            base.TestBinaryFieldOffsetLength();
+        }
+
+        [Test]
+        public override void TestNumericField()
+        {
+            base.TestNumericField();
+        }
+
+        [Test]
+        public override void TestIndexedBit()
+        {
+            base.TestIndexedBit();
+        }
+
+        [Test]
+        public override void TestReadSkip()
+        {
+            base.TestReadSkip();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestEmptyDocs()
+        {
+            base.TestEmptyDocs();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestConcurrentReads()
+        {
+            base.TestConcurrentReads();
+        }
+
+        [Test]
+        public override void TestWriteReadMerge()
+        {
+            base.TestWriteReadMerge();
+        }
+
+        [Test, LongRunningTest]
+        public override void TestBigDocuments()
+        {
+            base.TestBigDocuments();
+        }
+
+        [Test]
+        public override void TestBulkMergeWithDeletes()
+        {
+            base.TestBulkMergeWithDeletes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
index a5fe4c5..527deea 100644
--- a/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests.Codecs/SimpleText/TestSimpleTextTermVectorsFormat.cs
@@ -30,5 +30,71 @@ namespace Lucene.Net.Codecs.SimpleText
                 return new SimpleTextCodec();
             }
         }
+
+        #region BaseTermVectorsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        // only one doc with vectors
+        public override void TestRareVectors()
+        {
+            base.TestRareVectors();
+        }
+
+        [Test]
+        public override void TestHighFreqs()
+        {
+            base.TestHighFreqs();
+        }
+
+        [Test]
+        public override void TestLotsOfFields()
+        {
+            base.TestLotsOfFields();
+        }
+
+        [Test, Timeout(300000)]
+        // different options for the same field
+        public override void TestMixedOptions()
+        {
+            base.TestMixedOptions();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestMerge()
+        {
+            base.TestMerge();
+        }
+
+        [Test]
+        // run random tests from different threads to make sure the per-thread clones
+        // don't share mutable data
+        public override void TestClone()
+        {
+            base.TestClone();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs b/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
index 164f275..fdc0e95 100644
--- a/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
+++ b/src/Lucene.Net.Tests.Misc/Index/Sorter/IndexSortingTest.cs
@@ -87,5 +87,61 @@ namespace Lucene.Net.Index.Sorter
             reader = SlowCompositeReaderWrapper.Wrap(DirectoryReader.Open(dir));
             assertFalse("index should not have deletions", reader.HasDeletions);
         }
+
+
+        #region SorterTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestBinaryDocValuesField()
+        {
+            base.TestBinaryDocValuesField();
+        }
+
+        [Test]
+        public override void TestDocsAndPositionsEnum()
+        {
+            base.TestDocsAndPositionsEnum();
+        }
+
+        [Test]
+        public override void TestDocsEnum()
+        {
+            base.TestDocsEnum();
+        }
+
+        [Test]
+        public override void TestNormValues()
+        {
+            base.TestNormValues();
+        }
+
+        [Test]
+        public override void TestNumericDocValuesField()
+        {
+            base.TestNumericDocValuesField();
+        }
+
+        [Test]
+        public override void TestSortedDocValuesField()
+        {
+            base.TestSortedDocValuesField();
+        }
+
+        [Test]
+        public override void TestSortedSetDocValuesField()
+        {
+            base.TestSortedSetDocValuesField();
+        }
+
+        [Test]
+        public override void TestTermVectors()
+        {
+            base.TestTermVectors();
+        }
+
+        #endregion
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs b/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
index 2cff135..99623ad 100644
--- a/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
+++ b/src/Lucene.Net.Tests.Misc/Index/Sorter/SorterTestBase.cs
@@ -230,7 +230,7 @@ namespace Lucene.Net.Index.Sorter
             dir.Dispose();
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestBinaryDocValuesField()
         {
             BinaryDocValues dv = reader.GetBinaryDocValues(BINARY_DV_FIELD);
@@ -242,7 +242,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsAndPositionsEnum()
         {
             TermsEnum termsEnum = reader.Terms(DOC_POSITIONS_FIELD).Iterator(null);
@@ -322,7 +322,7 @@ namespace Lucene.Net.Index.Sorter
             return bits;
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDocsEnum()
         {
             Bits mappedLiveDocs = RandomLiveDocs(reader.MaxDoc);
@@ -369,7 +369,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestNormValues()
         {
             NumericDocValues dv = reader.GetNormValues(NORMS_FIELD);
@@ -380,7 +380,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestNumericDocValuesField()
         {
             NumericDocValues dv = reader.GetNumericDocValues(NUMERIC_DV_FIELD);
@@ -391,7 +391,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedDocValuesField()
         {
             SortedDocValues dv = reader.GetSortedDocValues(SORTED_DV_FIELD);
@@ -404,7 +404,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestSortedSetDocValuesField()
         {
             AssumeTrue("default codec does not support SORTED_SET", DefaultCodecSupportsSortedSet());
@@ -423,7 +423,7 @@ namespace Lucene.Net.Index.Sorter
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestTermVectors()
         {
             int maxDoc = reader.MaxDoc;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs b/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
index cb2b38e..93b234a 100644
--- a/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
+++ b/src/Lucene.Net.Tests.Misc/Index/Sorter/SortingAtomicReaderTest.cs
@@ -79,5 +79,61 @@ namespace Lucene.Net.Index.Sorter
                 assertEquals("Cannot sort an index with a Sort that refers to the relevance score", e.Message);
             }
         }
+
+
+        #region SorterTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestBinaryDocValuesField()
+        {
+            base.TestBinaryDocValuesField();
+        }
+
+        [Test]
+        public override void TestDocsAndPositionsEnum()
+        {
+            base.TestDocsAndPositionsEnum();
+        }
+
+        [Test]
+        public override void TestDocsEnum()
+        {
+            base.TestDocsEnum();
+        }
+
+        [Test]
+        public override void TestNormValues()
+        {
+            base.TestNormValues();
+        }
+
+        [Test]
+        public override void TestNumericDocValuesField()
+        {
+            base.TestNumericDocValuesField();
+        }
+
+        [Test]
+        public override void TestSortedDocValuesField()
+        {
+            base.TestSortedDocValuesField();
+        }
+
+        [Test]
+        public override void TestSortedSetDocValuesField()
+        {
+            base.TestSortedSetDocValuesField();
+        }
+
+        [Test]
+        public override void TestTermVectors()
+        {
+            base.TestTermVectors();
+        }
+
+        #endregion
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs b/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
index 2b71216..577f27b 100644
--- a/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Classic/TestQueryParser.cs
@@ -551,5 +551,255 @@ namespace Lucene.Net.QueryParsers.Classic
             assertEquals(expected, qp.Parse("\"\u4e2d\u56fd\"~3^2"));
         }
 
+
+        #region QueryParserTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestCJK()
+        {
+            base.TestCJK();
+        }
+
+        [Test]
+        public override void TestCJKTerm()
+        {
+            base.TestCJKTerm();
+        }
+
+        [Test]
+        public override void TestCJKBoostedTerm()
+        {
+            base.TestCJKBoostedTerm();
+        }
+
+        [Test]
+        public override void TestCJKPhrase()
+        {
+            base.TestCJKPhrase();
+        }
+
+        [Test]
+        public override void TestCJKBoostedPhrase()
+        {
+            base.TestCJKBoostedPhrase();
+        }
+
+        [Test]
+        public override void TestCJKSloppyPhrase()
+        {
+            base.TestCJKSloppyPhrase();
+        }
+
+        [Test]
+        public override void TestAutoGeneratePhraseQueriesOn()
+        {
+            base.TestAutoGeneratePhraseQueriesOn();
+        }
+
+        [Test]
+        public override void TestSimple()
+        {
+            base.TestSimple();
+        }
+
+        [Test]
+        public override void TestOperatorVsWhitespace()
+        {
+            base.TestOperatorVsWhitespace();
+        }
+
+        [Test]
+        public override void TestPunct()
+        {
+            base.TestPunct();
+        }
+
+        [Test]
+        public override void TestSlop()
+        {
+            base.TestSlop();
+        }
+
+        [Test]
+        public override void TestNumber()
+        {
+            base.TestNumber();
+        }
+
+        [Test]
+        public override void TestWildcard()
+        {
+            base.TestWildcard();
+        }
+
+        [Test]
+        public override void TestLeadingWildcardType()
+        {
+            base.TestLeadingWildcardType();
+        }
+
+        [Test]
+        public override void TestQPA()
+        {
+            base.TestQPA();
+        }
+
+        [Test]
+        public override void TestRange()
+        {
+            base.TestRange();
+        }
+
+        [Test]
+        public override void TestRangeWithPhrase()
+        {
+            base.TestRangeWithPhrase();
+        }
+
+        [Test]
+        public override void TestDateRange()
+        {
+            base.TestDateRange();
+        }
+
+        [Test]
+        public override void TestEscaped()
+        {
+            base.TestEscaped();
+        }
+
+        [Test]
+        public override void TestEscapedVsQuestionMarkAsWildcard()
+        {
+            base.TestEscapedVsQuestionMarkAsWildcard();
+        }
+
+        [Test]
+        public override void TestQueryStringEscaping()
+        {
+            base.TestQueryStringEscaping();
+        }
+
+        [Test]
+        public override void TestTabNewlineCarriageReturn()
+        {
+            base.TestTabNewlineCarriageReturn();
+        }
+
+        [Test]
+        public override void TestSimpleDAO()
+        {
+            base.TestSimpleDAO();
+        }
+
+        [Test]
+        public override void TestBoost()
+        {
+            base.TestBoost();
+        }
+
+        [Test]
+        public override void TestException()
+        {
+            base.TestException();
+        }
+
+        [Test]
+        public override void TestBooleanQuery()
+        {
+            base.TestBooleanQuery();
+        }
+
+        [Test]
+        public override void TestPrecedence()
+        {
+            base.TestPrecedence();
+        }
+
+        [Test]
+        public override void TestEscapedWildcard()
+        {
+            base.TestEscapedWildcard();
+        }
+
+        [Test]
+        public override void TestRegexps()
+        {
+            base.TestRegexps();
+        }
+
+        [Test]
+        public override void TestStopwords()
+        {
+            base.TestStopwords();
+        }
+
+        [Test]
+        public override void TestPositionIncrement()
+        {
+            base.TestPositionIncrement();
+        }
+
+        [Test]
+        public override void TestMatchAllDocs()
+        {
+            base.TestMatchAllDocs();
+        }
+
+        // LUCENE-2002: make sure defaults for StandardAnalyzer's
+        // enableStopPositionIncr & QueryParser's enablePosIncr
+        // "match"
+        [Test]
+        public override void TestPositionIncrements()
+        {
+            base.TestPositionIncrements();
+        }
+
+        [Test]
+        public override void TestCollatedRange()
+        {
+            base.TestCollatedRange();
+        }
+
+        [Test]
+        public override void TestDistanceAsEditsParsing()
+        {
+            base.TestDistanceAsEditsParsing();
+        }
+
+        [Test]
+        public override void TestPhraseQueryToString()
+        {
+            base.TestPhraseQueryToString();
+        }
+
+        [Test]
+        public override void TestParseWildcardAndPhraseQueries()
+        {
+            base.TestParseWildcardAndPhraseQueries();
+        }
+
+        [Test]
+        public override void TestPhraseQueryPositionIncrements()
+        {
+            base.TestPhraseQueryPositionIncrements();
+        }
+
+        [Test]
+        public override void TestMatchAllQueryParsing()
+        {
+            base.TestMatchAllQueryParsing();
+        }
+
+        [Test]
+        public override void TestNestedAndClausesFoo()
+        {
+            base.TestNestedAndClausesFoo();
+        }
+
+        #endregion
     }
 }


[52/58] [abbrv] lucenenet git commit: Added missing fail() in Grouping.TestGrouping test

Posted by ni...@apache.org.
Added missing fail() in Grouping.TestGrouping test


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

Branch: refs/heads/grouping
Commit: 5c9a388e098bdcc25fda89395ab8449f1480d32a
Parents: dd24cf3
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 23:22:38 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:20 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5c9a388e/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index ddef166..dc4743e 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -465,13 +465,9 @@ namespace Lucene.Net.Search.Grouping
                     {
                         return sf.Reverse ? -cmp : cmp;
                     }
-                    else
-                    {
-                        // should never get here
-                    }
                 }
                 // Our sort always fully tie breaks:
-                //fail();
+                fail();
                 return 0;
             }
         }


[17/58] [abbrv] lucenenet git commit: Revert "HACK: Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context."

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
index dc18580..2ce76f3 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene45/TestLucene45DocValuesFormat.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Codecs.Lucene45
 {
     /*
@@ -36,530 +34,5 @@ namespace Lucene.Net.Codecs.Lucene45
                 return Codec_Renamed;
             }
         }
-
-        #region BaseCompressingDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestUniqueValuesCompression()
-        {
-            base.TestUniqueValuesCompression();
-        }
-
-        [Test]
-        public override void TestDateCompression()
-        {
-            base.TestDateCompression();
-        }
-
-        [Test]
-        public override void TestSingleBigValueCompression()
-        {
-            base.TestSingleBigValueCompression();
-        }
-
-        #endregion
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
index cbf656c..bf0a5fe 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldDocValuesFormat.cs
@@ -153,506 +153,5 @@ namespace Lucene.Net.Codecs.Perfield
                 }
             }
         }
-
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
index 05751f9..d2275e8 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Perfield/TestPerFieldPostingsFormat.cs
@@ -45,56 +45,5 @@ namespace Lucene.Net.Codecs.Perfield
             //LUCENE TO-DO
             AssumeTrue("The MockRandom PF randomizes content on the fly, so we can't check it", false);
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
-
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs b/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
index 628ddc0..70ee586 100644
--- a/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestDocValuesFormat.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Index
 {
     /*
@@ -41,506 +39,5 @@ namespace Lucene.Net.Index
         {
             return TestUtil.FieldSupportsHugeBinaryDocValues(field);
         }
-
-
-        #region BaseDocValuesFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestOneNumber()
-        {
-            base.TestOneNumber();
-        }
-
-        [Test]
-        public override void TestOneFloat()
-        {
-            base.TestOneFloat();
-        }
-
-        [Test]
-        public override void TestTwoNumbers()
-        {
-            base.TestTwoNumbers();
-        }
-
-        [Test]
-        public override void TestTwoBinaryValues()
-        {
-            base.TestTwoBinaryValues();
-        }
-
-        [Test]
-        public override void TestTwoFieldsMixed()
-        {
-            base.TestTwoFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed()
-        {
-            base.TestThreeFieldsMixed();
-        }
-
-        [Test]
-        public override void TestThreeFieldsMixed2()
-        {
-            base.TestThreeFieldsMixed2();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsNumeric()
-        {
-            base.TestTwoDocumentsNumeric();
-        }
-
-        [Test]
-        public override void TestTwoDocumentsMerged()
-        {
-            base.TestTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestBigNumericRange()
-        {
-            base.TestBigNumericRange();
-        }
-
-        [Test]
-        public override void TestBigNumericRange2()
-        {
-            base.TestBigNumericRange2();
-        }
-
-        [Test]
-        public override void TestBytes()
-        {
-            base.TestBytes();
-        }
-
-        [Test]
-        public override void TestBytesTwoDocumentsMerged()
-        {
-            base.TestBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedBytes()
-        {
-            base.TestSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocuments()
-        {
-            base.TestSortedBytesTwoDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesThreeDocuments()
-        {
-            base.TestSortedBytesThreeDocuments();
-        }
-
-        [Test]
-        public override void TestSortedBytesTwoDocumentsMerged()
-        {
-            base.TestSortedBytesTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedMergeAwayAllValues()
-        {
-            base.TestSortedMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestBytesWithNewline()
-        {
-            base.TestBytesWithNewline();
-        }
-
-        [Test]
-        public override void TestMissingSortedBytes()
-        {
-            base.TestMissingSortedBytes();
-        }
-
-        [Test]
-        public override void TestSortedTermsEnum()
-        {
-            base.TestSortedTermsEnum();
-        }
-
-        [Test]
-        public override void TestEmptySortedBytes()
-        {
-            base.TestEmptySortedBytes();
-        }
-
-        [Test]
-        public override void TestEmptyBytes()
-        {
-            base.TestEmptyBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalBytes()
-        {
-            base.TestVeryLargeButLegalBytes();
-        }
-
-        [Test]
-        public override void TestVeryLargeButLegalSortedBytes()
-        {
-            base.TestVeryLargeButLegalSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytes()
-        {
-            base.TestCodecUsesOwnBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytes()
-        {
-            base.TestCodecUsesOwnSortedBytes();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnBytesEachTime()
-        {
-            base.TestCodecUsesOwnBytesEachTime();
-        }
-
-        [Test]
-        public override void TestCodecUsesOwnSortedBytesEachTime()
-        {
-            base.TestCodecUsesOwnSortedBytesEachTime();
-        }
-
-        /*
-         * Simple test case to show how to use the API
-         */
-        [Test]
-        public override void TestDocValuesSimple()
-        {
-            base.TestDocValuesSimple();
-        }
-
-        [Test]
-        public override void TestRandomSortedBytes()
-        {
-            base.TestRandomSortedBytes();
-        }
-
-        [Test]
-        public override void TestBooleanNumericsVsStoredFields()
-        {
-            base.TestBooleanNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteNumericsVsStoredFields()
-        {
-            base.TestByteNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestByteMissingVsFieldCache()
-        {
-            base.TestByteMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestShortNumericsVsStoredFields()
-        {
-            base.TestShortNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestShortMissingVsFieldCache()
-        {
-            base.TestShortMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestIntNumericsVsStoredFields()
-        {
-            base.TestIntNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestIntMissingVsFieldCache()
-        {
-            base.TestIntMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestLongNumericsVsStoredFields()
-        {
-            base.TestLongNumericsVsStoredFields();
-        }
-
-        [Test]
-        public override void TestLongMissingVsFieldCache()
-        {
-            base.TestLongMissingVsFieldCache();
-        }
-
-        [Test]
-        public override void TestBinaryFixedLengthVsStoredFields()
-        {
-            base.TestBinaryFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestBinaryVariableLengthVsStoredFields()
-        {
-            base.TestBinaryVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsStoredFields()
-        {
-            base.TestSortedFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedFixedLengthVsFieldCache()
-        {
-            base.TestSortedFixedLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsFieldCache()
-        {
-            base.TestSortedVariableLengthVsFieldCache();
-        }
-
-        [Test]
-        public override void TestSortedVariableLengthVsStoredFields()
-        {
-            base.TestSortedVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetOneValue()
-        {
-            base.TestSortedSetOneValue();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoFields()
-        {
-            base.TestSortedSetTwoFields();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsMerged()
-        {
-            base.TestSortedSetTwoDocumentsMerged();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValues()
-        {
-            base.TestSortedSetTwoValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoValuesUnordered()
-        {
-            base.TestSortedSetTwoValuesUnordered();
-        }
-
-        [Test]
-        public override void TestSortedSetThreeValuesTwoDocs()
-        {
-            base.TestSortedSetThreeValuesTwoDocs();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissing()
-        {
-            base.TestSortedSetTwoDocumentsLastMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsLastMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsLastMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissing()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissing();
-        }
-
-        [Test]
-        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
-        {
-            base.TestSortedSetTwoDocumentsFirstMissingMerge();
-        }
-
-        [Test]
-        public override void TestSortedSetMergeAwayAllValues()
-        {
-            base.TestSortedSetMergeAwayAllValues();
-        }
-
-        [Test]
-        public override void TestSortedSetTermsEnum()
-        {
-            base.TestSortedSetTermsEnum();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
-        {
-            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
-        }
-
-        [Test]
-        public override void TestSortedSetFixedLengthVsUninvertedField()
-        {
-            base.TestSortedSetFixedLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestSortedSetVariableLengthVsUninvertedField()
-        {
-            base.TestSortedSetVariableLengthVsUninvertedField();
-        }
-
-        [Test]
-        public override void TestGCDCompression()
-        {
-            base.TestGCDCompression();
-        }
-
-        [Test]
-        public override void TestZeros()
-        {
-            base.TestZeros();
-        }
-
-        [Test]
-        public override void TestZeroOrMin()
-        {
-            base.TestZeroOrMin();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissing()
-        {
-            base.TestTwoNumbersOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoNumbersOneMissingWithMerging()
-        {
-            base.TestTwoNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeNumbersOneMissingWithMerging()
-        {
-            base.TestThreeNumbersOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissing()
-        {
-            base.TestTwoBytesOneMissing();
-        }
-
-        [Test]
-        public override void TestTwoBytesOneMissingWithMerging()
-        {
-            base.TestTwoBytesOneMissingWithMerging();
-        }
-
-        [Test]
-        public override void TestThreeBytesOneMissingWithMerging()
-        {
-            base.TestThreeBytesOneMissingWithMerging();
-        }
-
-        // LUCENE-4853
-        [Test]
-        public override void TestHugeBinaryValues()
-        {
-            base.TestHugeBinaryValues();
-        }
-
-        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
-        [Test]
-        public override void TestHugeBinaryValueLimit()
-        {
-            base.TestHugeBinaryValueLimit();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads()
-        {
-            base.TestThreads();
-        }
-
-        /// <summary>
-        /// Tests dv against stored fields with threads (all types + missing)
-        /// </summary>
-        [Test]
-        public override void TestThreads2()
-        {
-            base.TestThreads2();
-        }
-
-        // LUCENE-5218
-        [Test]
-        public override void TestEmptyBinaryValueOnPageSizes()
-        {
-            base.TestEmptyBinaryValueOnPageSizes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs b/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
index 921b719..e99678b 100644
--- a/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestLogMergePolicy.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Index
 {
     /*
@@ -25,18 +23,5 @@ namespace Lucene.Net.Index
         {
             return NewLogMergePolicy(Random());
         }
-
-        #region BaseMergePolicyTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestForceMergeNotNeeded()
-        {
-            base.TestForceMergeNotNeeded();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs b/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
index c48b98f..7f425f7 100644
--- a/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestNumericDocValuesUpdates.cs
@@ -1527,7 +1527,7 @@ namespace Lucene.Net.Index
             dir.Dispose();
         }
 
-        [Test, Timeout(120000)]
+        [Test]
         public virtual void TestTonsOfUpdates()
         {
             // LUCENE-5248: make sure that when there are many updates, we don't use too much RAM

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs b/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
index 7d49c1b..70c47cc 100644
--- a/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestPersistentSnapshotDeletionPolicy.cs
@@ -208,55 +208,5 @@ namespace Lucene.Net.Index
             Assert.AreEqual(0, psdp.SnapshotCount, "Should have no snapshots !");
             dir.Dispose();
         }
-
-
-        #region TestSnapshotDeletionPolicy
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestSnapshotDeletionPolicy_Mem()
-        {
-            base.TestSnapshotDeletionPolicy_Mem();
-        }
-
-        [Test]
-        public override void TestBasicSnapshots()
-        {
-            base.TestBasicSnapshots();
-        }
-
-        [Test]
-        public override void TestMultiThreadedSnapshotting()
-        {
-            base.TestMultiThreadedSnapshotting();
-        }
-
-        [Test]
-        public override void TestRollbackToOldSnapshot()
-        {
-            base.TestRollbackToOldSnapshot();
-        }
-
-        [Test]
-        public override void TestReleaseSnapshot()
-        {
-            base.TestReleaseSnapshot();
-        }
-
-        [Test]
-        public override void TestSnapshotLastCommitTwice()
-        {
-            base.TestSnapshotLastCommitTwice();
-        }
-
-        [Test]
-        public override void TestMissingCommits()
-        {
-            base.TestMissingCommits();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs b/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
index 20c6b07..427aa96 100644
--- a/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestPostingsFormat.cs
@@ -41,55 +41,5 @@ namespace Lucene.Net.Index
         {
             AssumeTrue("The MockRandom PF randomizes content on the fly, so we can't check it", false);
         }
-
-
-        #region BasePostingsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestDocsOnly()
-        {
-            base.TestDocsOnly();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqs()
-        {
-            base.TestDocsAndFreqs();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositions()
-        {
-            base.TestDocsAndFreqsAndPositions();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndPayloads();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsets()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsets();
-        }
-
-        [Test]
-        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
-        {
-            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
index 31ed10c..902db7f 100644
--- a/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestStoredFieldsFormat.cs
@@ -47,88 +47,5 @@ namespace Lucene.Net.Index
             // and merge into newly formed 3.x segments.
             base.TestWriteReadMerge();
         }
-
-
-        #region BaseStoredFieldsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestRandomStoredFields()
-        {
-            base.TestRandomStoredFields();
-        }
-
-        [Test]
-        // LUCENE-1727: make sure doc fields are stored in order
-        public override void TestStoredFieldsOrder()
-        {
-            base.TestStoredFieldsOrder();
-        }
-
-        [Test]
-        // LUCENE-1219
-        public override void TestBinaryFieldOffsetLength()
-        {
-            base.TestBinaryFieldOffsetLength();
-        }
-
-        [Test]
-        public override void TestNumericField()
-        {
-            base.TestNumericField();
-        }
-
-        [Test]
-        public override void TestIndexedBit()
-        {
-            base.TestIndexedBit();
-        }
-
-        [Test]
-        public override void TestReadSkip()
-        {
-            base.TestReadSkip();
-        }
-
-        [Test]
-        public override void TestEmptyDocs()
-        {
-            base.TestEmptyDocs();
-        }
-
-        [Test]
-        public override void TestConcurrentReads()
-        {
-            base.TestConcurrentReads();
-        }
-
-        [Test, Timeout(120000)]
-        public override void TestBigDocuments()
-        {
-            base.TestBigDocuments();
-        }
-
-        [Test]
-        public override void TestBulkMergeWithDeletes()
-        {
-            base.TestBulkMergeWithDeletes();
-        }
-
-        #endregion
-
-        #region BaseIndexFileFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestMergeStability()
-        {
-            base.TestMergeStability();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
index dac8fa8..38f08d4 100644
--- a/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestTermVectorsFormat.cs
@@ -58,60 +58,5 @@ namespace Lucene.Net.Index
         {
             AssumeTrue("The MockRandom PF randomizes content on the fly, so we can't check it", false);
         }
-
-
-
-        #region BaseTermVectorsFormatTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        // only one doc with vectors
-        public override void TestRareVectors()
-        {
-            base.TestRareVectors();
-        }
-
-        [Test]
-        public override void TestHighFreqs()
-        {
-            base.TestHighFreqs();
-        }
-
-        [Test]
-        public override void TestLotsOfFields()
-        {
-            base.TestLotsOfFields();
-        }
-
-        [Test]
-        // different options for the same field
-        public override void TestMixedOptions()
-        {
-            base.TestMixedOptions();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestMerge()
-        {
-            base.TestMerge();
-        }
-
-        [Test]
-        // run random tests from different threads to make sure the per-thread clones
-        // don't share mutable data
-        public override void TestClone()
-        {
-            base.TestClone();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs b/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
index ede9691..922551c 100644
--- a/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
+++ b/src/Lucene.Net.Tests/core/Index/TestTieredMergePolicy.cs
@@ -273,19 +273,5 @@ namespace Lucene.Net.Index
 
             // TODO: Add more checks for other non-double setters!
         }
-
-
-        #region BaseMergePolicyTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestForceMergeNotNeeded()
-        {
-            base.TestForceMergeNotNeeded();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs b/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
index 16a6d17..96ec2f4 100644
--- a/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
+++ b/src/Lucene.Net.Tests/core/Search/BaseTestRangeFilter.cs
@@ -192,7 +192,7 @@ namespace Lucene.Net.Search
             }
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestPad()
         {
             int[] tests = new int[] { -9999999, -99560, -100, -3, -1, 0, 3, 9, 10, 1000, 999999999 };

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
index 307c51f..735dc0c 100644
--- a/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
+++ b/src/Lucene.Net.Tests/core/Search/Spans/TestSpanExplanationsOfNonMatches.cs
@@ -33,219 +33,5 @@ namespace Lucene.Net.Search.Spans
         {
             CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
         }
-
-
-        #region TestSpanExplanations
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestST1()
-        {
-            base.TestST1();
-        }
-
-        [Test]
-        public override void TestST2()
-        {
-            base.TestST2();
-        }
-
-        [Test]
-        public override void TestST4()
-        {
-            base.TestST4();
-        }
-
-        [Test]
-        public override void TestST5()
-        {
-            base.TestST5();
-        }
-
-        /* some SpanFirstQueries */
-
-        [Test]
-        public override void TestSF1()
-        {
-            base.TestSF1();
-        }
-
-        [Test]
-        public override void TestSF2()
-        {
-            base.TestSF2();
-        }
-
-        [Test]
-        public override void TestSF4()
-        {
-            base.TestSF4();
-        }
-
-        [Test]
-        public override void TestSF5()
-        {
-            base.TestSF5();
-        }
-
-        [Test]
-        public override void TestSF6()
-        {
-            base.TestSF6();
-        }
-
-        /* some SpanOrQueries */
-
-        [Test]
-        public override void TestSO1()
-        {
-            base.TestSO1();
-        }
-
-        [Test]
-        public override void TestSO2()
-        {
-            base.TestSO2();
-        }
-
-        [Test]
-        public override void TestSO3()
-        {
-            base.TestSO3();
-        }
-
-        [Test]
-        public override void TestSO4()
-        {
-            base.TestSO4();
-        }
-
-        /* some SpanNearQueries */
-
-        [Test]
-        public override void TestSNear1()
-        {
-            base.TestSNear1();
-        }
-
-        [Test]
-        public override void TestSNear2()
-        {
-            base.TestSNear2();
-        }
-
-        [Test]
-        public override void TestSNear3()
-        {
-            base.TestSNear3();
-        }
-
-        [Test]
-        public override void TestSNear4()
-        {
-            base.TestSNear4();
-        }
-
-        [Test]
-        public override void TestSNear5()
-        {
-            base.TestSNear5();
-        }
-
-        [Test]
-        public override void TestSNear6()
-        {
-            base.TestSNear6();
-        }
-
-        [Test]
-        public override void TestSNear7()
-        {
-            base.TestSNear7();
-        }
-
-        [Test]
-        public override void TestSNear8()
-        {
-            base.TestSNear8();
-        }
-
-        [Test]
-        public override void TestSNear9()
-        {
-            base.TestSNear9();
-        }
-
-        [Test]
-        public override void TestSNear10()
-        {
-            base.TestSNear10();
-        }
-
-        [Test]
-        public override void TestSNear11()
-        {
-            base.TestSNear11();
-        }
-
-        /* some SpanNotQueries */
-
-        [Test]
-        public override void TestSNot1()
-        {
-            base.TestSNot1();
-        }
-
-        [Test]
-        public override void TestSNot2()
-        {
-            base.TestSNot2();
-        }
-
-        [Test]
-        public override void TestSNot4()
-        {
-            base.TestSNot4();
-        }
-
-        [Test]
-        public override void TestSNot5()
-        {
-            base.TestSNot5();
-        }
-
-        [Test]
-        public override void TestSNot7()
-        {
-            base.TestSNot7();
-        }
-
-        [Test]
-        public override void TestSNot10()
-        {
-            base.TestSNot10();
-        }
-
-        #endregion
-
-        #region TestExplanations
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-
-        /// <summary>
-        /// Placeholder: JUnit freaks if you don't have one test ... making
-        /// class abstract doesn't help
-        /// </summary>
-        [Test]
-        public override void TestNoop()
-        {
-            base.TestNoop();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
index 18a2759..fbfe049 100644
--- a/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestComplexExplanationsOfNonMatches.cs
@@ -33,165 +33,5 @@ namespace Lucene.Net.Search
         {
             CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
         }
-
-
-        #region TestComplexExplanations
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void Test1()
-        {
-            base.Test1();
-        }
-
-        [Test]
-        public override void Test2()
-        {
-            base.Test2();
-        }
-
-        // :TODO: we really need more crazy complex cases.
-
-        // //////////////////////////////////////////////////////////////////
-
-        // The rest of these aren't that complex, but they are <i>somewhat</i>
-        // complex, and they expose weakness in dealing with queries that match
-        // with scores of 0 wrapped in other queries
-
-        [Test]
-        public override void TestT3()
-        {
-            base.TestT3();
-        }
-
-        [Test]
-        public override void TestMA3()
-        {
-            base.TestMA3();
-        }
-
-        [Test]
-        public override void TestFQ5()
-        {
-            base.TestFQ5();
-        }
-
-        [Test]
-        public override void TestCSQ4()
-        {
-            base.TestCSQ4();
-        }
-
-        [Test]
-        public override void TestDMQ10()
-        {
-            base.TestDMQ10();
-        }
-
-        [Test]
-        public override void TestMPQ7()
-        {
-            base.TestMPQ7();
-        }
-
-        [Test]
-        public override void TestBQ12()
-        {
-            base.TestBQ12();
-        }
-
-        [Test]
-        public override void TestBQ13()
-        {
-            base.TestBQ13();
-        }
-
-        [Test]
-        public override void TestBQ18()
-        {
-            base.TestBQ18();
-        }
-
-        [Test]
-        public override void TestBQ21()
-        {
-            base.TestBQ21();
-        }
-
-        [Test]
-        public override void TestBQ22()
-        {
-            base.TestBQ22();
-        }
-
-        [Test]
-        public override void TestST3()
-        {
-            base.TestST3();
-        }
-
-        [Test]
-        public override void TestST6()
-        {
-            base.TestST6();
-        }
-
-        [Test]
-        public override void TestSF3()
-        {
-            base.TestSF3();
-        }
-
-        [Test]
-        public override void TestSF7()
-        {
-            base.TestSF7();
-        }
-
-        [Test]
-        public override void TestSNot3()
-        {
-            base.TestSNot3();
-        }
-
-        [Test]
-        public override void TestSNot6()
-        {
-            base.TestSNot6();
-        }
-
-        [Test]
-        public override void TestSNot8()
-        {
-            base.TestSNot8();
-        }
-
-        [Test]
-        public override void TestSNot9()
-        {
-            base.TestSNot9();
-        }
-
-        #endregion
-
-        #region TestExplanations
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-
-        /// <summary>
-        /// Placeholder: JUnit freaks if you don't have one test ... making
-        /// class abstract doesn't help
-        /// </summary>
-        [Test]
-        public override void TestNoop()
-        {
-            base.TestNoop();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestExplanations.cs b/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
index 18962f9..a528615 100644
--- a/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestExplanations.cs
@@ -261,7 +261,7 @@ namespace Lucene.Net.Search
         /// Placeholder: JUnit freaks if you don't have one test ... making
         /// class abstract doesn't help
         /// </summary>
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestNoop()
         {
             /* NOOP */

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
index f0e44a8..cc0d022 100644
--- a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRangeFilter.cs
@@ -590,19 +590,5 @@ namespace Lucene.Net.Search
             reader.Dispose();
             dir.Dispose();
         }
-
-
-        #region SorterTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestPad()
-        {
-            base.TestPad();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
index 1b923a3..0fc6843 100644
--- a/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestFieldCacheRewriteMethod.cs
@@ -60,22 +60,5 @@ namespace Lucene.Net.Search
             Assert.IsFalse(a1.Equals(b));
             QueryUtils.Check(a1);
         }
-
-
-
-        #region TestSnapshotDeletionPolicy
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// test a bunch of random regular expressions </summary>
-        [Test, Timeout(60000)]
-        public override void TestRegexps()
-        {
-            base.TestRegexps();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs b/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
index 7f95d2a..f52d360 100644
--- a/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestMultiTermConstantScore.cs
@@ -551,19 +551,5 @@ namespace Lucene.Net.Search
             result = search.Search(Csrq("rand", maxRP, null, T, F), null, numDocs).ScoreDocs;
             AssertEquals("max,nul,T,T", 1, result.Length);
         }
-
-
-        #region SorterTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestPad()
-        {
-            base.TestPad();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
index 5fec12f..304a837 100644
--- a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanations.cs
@@ -927,24 +927,5 @@ namespace Lucene.Net.Search
 
             Qtest(query, new int[] { 0, 1, 2, 3 });
         }
-
-
-        #region TestExplanations
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-
-        /// <summary>
-        /// Placeholder: JUnit freaks if you don't have one test ... making
-        /// class abstract doesn't help
-        /// </summary>
-        [Test]
-        public override void TestNoop()
-        {
-            base.TestNoop();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
index ee990c1..6b45673 100644
--- a/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestSimpleExplanationsOfNonMatches.cs
@@ -33,457 +33,5 @@ namespace Lucene.Net.Search
         {
             CheckHits.CheckNoMatchExplanations(q, FIELD, Searcher, expDocNrs);
         }
-
-
-        #region TestSimpleExplanations
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestT1()
-        {
-            base.TestT1();
-        }
-
-        [Test]
-        public override void TestT2()
-        {
-            base.TestT2();
-        }
-
-        /* MatchAllDocs */
-
-        [Test]
-        public override void TestMA1()
-        {
-            base.TestMA1();
-        }
-
-        [Test]
-        public override void TestMA2()
-        {
-            base.TestMA2();
-        }
-
-        /* some simple phrase tests */
-
-        [Test]
-        public override void TestP1()
-        {
-            base.TestP1();
-        }
-
-        [Test]
-        public override void TestP2()
-        {
-            base.TestP2();
-        }
-
-        [Test]
-        public override void TestP3()
-        {
-            base.TestP3();
-        }
-
-        [Test]
-        public override void TestP4()
-        {
-            base.TestP4();
-        }
-
-        [Test]
-        public override void TestP5()
-        {
-            base.TestP5();
-        }
-
-        [Test]
-        public override void TestP6()
-        {
-            base.TestP6();
-        }
-
-        [Test]
-        public override void TestP7()
-        {
-            base.TestP7();
-        }
-
-        /* some simple filtered query tests */
-
-        [Test]
-        public override void TestFQ1()
-        {
-            base.TestFQ1();
-        }
-
-        [Test]
-        public override void TestFQ2()
-        {
-            base.TestFQ2();
-        }
-
-        [Test]
-        public override void TestFQ3()
-        {
-            base.TestFQ3();
-        }
-
-        [Test]
-        public override void TestFQ4()
-        {
-            base.TestFQ4();
-        }
-
-        [Test]
-        public override void TestFQ6()
-        {
-            base.TestFQ6();
-        }
-
-        /* ConstantScoreQueries */
-
-        [Test]
-        public override void TestCSQ1()
-        {
-            base.TestCSQ1();
-        }
-
-        [Test]
-        public override void TestCSQ2()
-        {
-            base.TestCSQ2();
-        }
-
-        [Test]
-        public override void TestCSQ3()
-        {
-            base.TestCSQ3();
-        }
-
-        /* DisjunctionMaxQuery */
-
-        [Test]
-        public override void TestDMQ1()
-        {
-            base.TestDMQ1();
-        }
-
-        [Test]
-        public override void TestDMQ2()
-        {
-            base.TestDMQ2();
-        }
-
-        [Test]
-        public override void TestDMQ3()
-        {
-            base.TestDMQ3();
-        }
-
-        [Test]
-        public override void TestDMQ4()
-        {
-            base.TestDMQ4();
-        }
-
-        [Test]
-        public override void TestDMQ5()
-        {
-            base.TestDMQ5();
-        }
-
-        [Test]
-        public override void TestDMQ6()
-        {
-            base.TestDMQ6();
-        }
-
-        [Test]
-        public override void TestDMQ7()
-        {
-            base.TestDMQ7();
-        }
-
-        [Test]
-        public override void TestDMQ8()
-        {
-            base.TestDMQ8();
-        }
-
-        [Test]
-        public override void TestDMQ9()
-        {
-            base.TestDMQ9();
-        }
-
-        /* MultiPhraseQuery */
-
-        [Test]
-        public override void TestMPQ1()
-        {
-            base.TestMPQ1();
-        }
-
-        [Test]
-        public override void TestMPQ2()
-        {
-            base.TestMPQ2();
-        }
-
-        [Test]
-        public override void TestMPQ3()
-        {
-            base.TestMPQ3();
-        }
-
-        [Test]
-        public override void TestMPQ4()
-        {
-            base.TestMPQ4();
-        }
-
-        [Test]
-        public override void TestMPQ5()
-        {
-            base.TestMPQ5();
-        }
-
-        [Test]
-        public override void TestMPQ6()
-        {
-            base.TestMPQ6();
-        }
-
-        /* some simple tests of boolean queries containing term queries */
-
-        [Test]
-        public override void TestBQ1()
-        {
-            base.TestBQ1();
-        }
-
-        [Test]
-        public override void TestBQ2()
-        {
-            base.TestBQ2();
-        }
-
-        [Test]
-        public override void TestBQ3()
-        {
-            base.TestBQ3();
-        }
-
-        [Test]
-        public override void TestBQ4()
-        {
-            base.TestBQ4();
-        }
-
-        [Test]
-        public override void TestBQ5()
-        {
-            base.TestBQ5();
-        }
-
-        [Test]
-        public override void TestBQ6()
-        {
-            base.TestBQ6();
-        }
-
-        [Test]
-        public override void TestBQ7()
-        {
-            base.TestBQ7();
-        }
-
-        [Test]
-        public override void TestBQ8()
-        {
-            base.TestBQ8();
-        }
-
-        [Test]
-        public override void TestBQ9()
-        {
-            base.TestBQ9();
-        }
-
-        [Test]
-        public override void TestBQ10()
-        {
-            base.TestBQ10();
-        }
-
-        [Test]
-        public override void TestBQ11()
-        {
-            base.TestBQ11();
-        }
-
-        [Test]
-        public override void TestBQ14()
-        {
-            base.TestBQ14();
-        }
-
-        [Test]
-        public override void TestBQ15()
-        {
-            base.TestBQ15();
-        }
-
-        [Test]
-        public override void TestBQ16()
-        {
-            base.TestBQ16();
-        }
-
-        [Test]
-        public override void TestBQ17()
-        {
-            base.TestBQ17();
-        }
-
-        [Test]
-        public override void TestBQ19()
-        {
-            base.TestBQ19();
-        }
-
-        [Test]
-        public override void TestBQ20()
-        {
-            base.TestBQ20();
-        }
-
-        /* BQ of TQ: using alt so some fields have zero boost and some don't */
-
-        [Test]
-        public override void TestMultiFieldBQ1()
-        {
-            base.TestMultiFieldBQ1();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ2()
-        {
-            base.TestMultiFieldBQ2();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ3()
-        {
-            base.TestMultiFieldBQ3();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ4()
-        {
-            base.TestMultiFieldBQ4();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ5()
-        {
-            base.TestMultiFieldBQ5();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ6()
-        {
-            base.TestMultiFieldBQ6();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ7()
-        {
-            base.TestMultiFieldBQ7();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ8()
-        {
-            base.TestMultiFieldBQ8();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ9()
-        {
-            base.TestMultiFieldBQ9();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQ10()
-        {
-            base.TestMultiFieldBQ10();
-        }
-
-        /* BQ of PQ: using alt so some fields have zero boost and some don't */
-
-        [Test]
-        public override void TestMultiFieldBQofPQ1()
-        {
-            base.TestMultiFieldBQofPQ1();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQofPQ2()
-        {
-            base.TestMultiFieldBQofPQ2();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQofPQ3()
-        {
-            base.TestMultiFieldBQofPQ3();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQofPQ4()
-        {
-            base.TestMultiFieldBQofPQ4();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQofPQ5()
-        {
-            base.TestMultiFieldBQofPQ5();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQofPQ6()
-        {
-            base.TestMultiFieldBQofPQ6();
-        }
-
-        [Test]
-        public override void TestMultiFieldBQofPQ7()
-        {
-            base.TestMultiFieldBQofPQ7();
-        }
-
-        #endregion
-
-        #region TestExplanations
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-
-        /// <summary>
-        /// Placeholder: JUnit freaks if you don't have one test ... making
-        /// class abstract doesn't help
-        /// </summary>
-        [Test]
-        public override void TestNoop()
-        {
-            base.TestNoop();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs b/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
index f8c9fb3..bb1c4d0 100644
--- a/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
+++ b/src/Lucene.Net.Tests/core/Search/TestTermRangeFilter.cs
@@ -177,19 +177,5 @@ namespace Lucene.Net.Search
             result = search.Search(q, TermRangeFilter.NewStringRange("rand", maxRP, null, T, F), numDocs).ScoreDocs;
             Assert.AreEqual(1, result.Length, "max,nul,T,T");
         }
-
-
-        #region SorterTestBase
-        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestPad()
-        {
-            base.TestPad();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file


[54/58] [abbrv] lucenenet git commit: Grouping: Fixed up documentation comments and license headers

Posted by ni...@apache.org.
Grouping: Fixed up documentation comments and license headers


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

Branch: refs/heads/grouping
Commit: a0a61e243005254e8a92358456fb34a77a678f4d
Parents: d0838cc
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Mon Nov 7 05:30:06 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:33 2016 +0700

----------------------------------------------------------------------
 .../AbstractAllGroupHeadsCollector.cs           |  29 +-
 .../AbstractAllGroupsCollector.cs               |  17 +
 .../AbstractDistinctValuesCollector.cs          |  21 ++
 .../AbstractFirstPassGroupingCollector.cs       |  28 +-
 .../AbstractGroupFacetCollector.cs              | 116 ++++---
 .../AbstractSecondPassGroupingCollector.cs      |  38 +-
 .../BlockGroupingCollector.cs                   | 138 +++++---
 src/Lucene.Net.Grouping/CollectedSearchGroup.cs |  21 +-
 .../Function/FunctionAllGroupHeadsCollector.cs  |  38 +-
 .../Function/FunctionAllGroupsCollector.cs      |  28 +-
 .../Function/FunctionDistinctValuesCollector.cs |  27 +-
 .../FunctionFirstPassGroupingCollector.cs       |  17 +
 .../FunctionSecondPassGroupingCollector.cs      |  17 +
 src/Lucene.Net.Grouping/GroupDocs.cs            |   1 +
 src/Lucene.Net.Grouping/GroupingSearch.cs       | 345 ++++++++++---------
 src/Lucene.Net.Grouping/SearchGroup.cs          |  73 +++-
 .../Term/TermAllGroupHeadsCollector.cs          | 110 ++++--
 .../Term/TermAllGroupsCollector.cs              |  17 +
 .../Term/TermDistinctValuesCollector.cs         |  38 +-
 .../Term/TermFirstPassGroupingCollector.cs      |  17 +
 .../Term/TermGroupFacetCollector.cs             |  52 ++-
 .../Term/TermSecondPassGroupingCollector.cs     |  17 +
 src/Lucene.Net.Grouping/TopGroups.cs            |   2 +-
 .../AbstractGroupingTestCase.cs                 |  17 +
 .../AllGroupHeadsCollectorTest.cs               |  17 +
 .../AllGroupsCollectorTest.cs                   |  17 +
 .../DistinctValuesCollectorTest.cs              |  17 +
 .../GroupFacetCollectorTest.cs                  |  17 +
 .../GroupingSearchTest.cs                       |  17 +
 29 files changed, 934 insertions(+), 375 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
index 279805e..bf3d984 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -3,6 +3,29 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
+    /// <summary>
+    /// This collector specializes in collecting the most relevant document (group head) for each group that match the query.
+    /// 
+    /// @lucene.experimental
+    /// </summary>
+    /// <typeparam name="GH"></typeparam>
     public abstract class AbstractAllGroupHeadsCollector<GH> : AbstractAllGroupHeadsCollector
         where GH : AbstractAllGroupHeadsCollector_GroupHead
     {
@@ -127,12 +150,10 @@ namespace Lucene.Net.Search.Grouping
         /// Contains the result of group head retrieval.
         /// To prevent new object creations of this class for every collect.
         /// </summary>
-        public class TemporalResult
+        protected class TemporalResult
         {
-
             public GH groupHead;
             public bool stop;
-
         }
     }
 
@@ -144,7 +165,7 @@ namespace Lucene.Net.Search.Grouping
     /// </para>
     /// </summary>
     /// <remarks>
-    /// LUCENENET: moved this class from of the <see cref="AbstractAllGroupHeadsCollector{TGroupValue}"/>,
+    /// LUCENENET: moved this class from being a nested class of <see cref="AbstractAllGroupHeadsCollector{TGroupValue}"/>,
     /// made it non-generic so the generic closing type doesn't need to be specified in classes that
     /// use <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> as a generic closing type, and renamed 
     /// it from GroupHead to <see cref="AbstractAllGroupHeadsCollector_GroupHead"/> to avoid naming conflicts with nested classes 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
index 6f1edb4..a40d0d7 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupsCollector.cs
@@ -3,6 +3,23 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// A collector that collects all groups that match the
     /// query. Only the group value is collected, and the order

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
index f832b1b..5acc02f 100644
--- a/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractDistinctValuesCollector.cs
@@ -2,6 +2,23 @@
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// A second pass grouping collector that keeps track of distinct values for a specified field for the top N group.
     /// 
@@ -80,6 +97,10 @@ namespace Lucene.Net.Search.Grouping
     /// <typeparam name="GC"></typeparam>
     public interface IAbstractDistinctValuesCollector<out GC>
     {
+        /// <summary>
+        /// Returns all unique values for each top N group.
+        /// </summary>
+        /// <returns>all unique values for each top N group</returns>
         IEnumerable<GC> Groups { get; }
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
index aae0591..62440f1 100644
--- a/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractFirstPassGroupingCollector.cs
@@ -7,6 +7,23 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// FirstPassGroupingCollector is the first of two passes necessary
     /// to collect grouped hits.  This pass gathers the top N sorted
@@ -14,7 +31,7 @@ namespace Lucene.Net.Search.Grouping
     /// is internally collected.
     /// 
     /// <para>
-    /// See {@link org.apache.lucene.search.grouping} for more
+    /// See <a href="https://github.com/apache/lucene-solr/blob/releases/lucene-solr/4.8.0/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html">org.apache.lucene.search.grouping</a> for more
     /// details including a full code example.
     /// </para>
     /// @lucene.experimental
@@ -39,7 +56,7 @@ namespace Lucene.Net.Search.Grouping
         /// Create the first pass collector.
         /// </summary>
         /// <param name="groupSort">
-        /// The {@link Sort} used to sort the
+        /// The <see cref="Sort"/> used to sort the
         /// groups.  The top sorted document within each group
         /// according to groupSort, determines how that group
         /// sorts against other groups.  This must be non-null,
@@ -404,12 +421,11 @@ namespace Lucene.Net.Search.Grouping
 
     /// <summary>
     /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// to simulate Java's wildcard generics.
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
     public interface IAbstractFirstPassGroupingCollector<out TGroupValue>
     {
-        // LUCENENET NOTE: We must use IEnumerable rather than ICollection here because we need
-        // this to be covariant
         /// <summary>
         /// Returns top groups, starting from offset.  This may
         /// return null, if no groups were collected, or if the
@@ -418,6 +434,10 @@ namespace Lucene.Net.Search.Grouping
         /// <param name="groupOffset">The offset in the collected groups</param>
         /// <param name="fillFields">Whether to fill to <see cref="SearchGroup.sortValues"/></param>
         /// <returns>top groups, starting from offset</returns>
+        /// <remarks>
+        /// LUCENENET NOTE: We must use <see cref="IEnumerable{TGroupValue}"/> rather than 
+        /// <see cref="ICollection{TGroupValue}"/> here because we need this to be covariant
+        /// </remarks>
         IEnumerable<ISearchGroup<TGroupValue>> GetTopGroups(int groupOffset, bool fillFields);
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
index 9a079e8..6e3e014 100644
--- a/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractGroupFacetCollector.cs
@@ -4,6 +4,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Base class for computing grouped facets.
     /// @lucene.experimental
@@ -28,17 +45,18 @@ namespace Lucene.Net.Search.Grouping
             segmentResults = new List<AbstractSegmentResult>();
         }
 
-        /**
-         * Returns grouped facet results that were computed over zero or more segments.
-         * Grouped facet counts are merged from zero or more segment results.
-         *
-         * @param size The total number of facets to include. This is typically offset + limit
-         * @param minCount The minimum count a facet entry should have to be included in the grouped facet result
-         * @param orderByCount Whether to sort the facet entries by facet entry count. If <code>false</code> then the facets
-         *                     are sorted lexicographically in ascending order.
-         * @return grouped facet results
-         * @throws IOException If I/O related errors occur during merging segment grouped facet counts.
-         */
+        /// <summary>
+        /// Returns grouped facet results that were computed over zero or more segments.
+        /// Grouped facet counts are merged from zero or more segment results.
+        /// </summary>
+        /// <param name="size">The total number of facets to include. This is typically offset + limit</param>
+        /// <param name="minCount">The minimum count a facet entry should have to be included in the grouped facet result</param>
+        /// <param name="orderByCount">
+        /// Whether to sort the facet entries by facet entry count. If <c>false</c> then the facets
+        /// are sorted lexicographically in ascending order.
+        /// </param>
+        /// <returns>grouped facet results</returns>
+        /// <exception cref="IOException">If I/O related errors occur during merging segment grouped facet counts.</exception>
         public GroupedFacetResult MergeSegmentResults(int size, int minCount, bool orderByCount)
         {
             if (segmentFacetCounts != null)
@@ -126,9 +144,9 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        /**
-         * The grouped facet result. Containing grouped facet entries, total count and total missing count.
-         */
+        /// <summary>
+        /// The grouped facet result. Containing grouped facet entries, total count and total missing count.
+        /// </summary>
         public class GroupedFacetResult
         {
             private readonly static IComparer<FacetEntry> orderByCountAndValue = new OrderByCountAndValueComparer();
@@ -175,14 +193,13 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-            /**
-             * Returns a list of facet entries to be rendered based on the specified offset and limit.
-             * The facet entries are retrieved from the facet entries collected during merging.
-             *
-             * @param offset The offset in the collected facet entries during merging
-             * @param limit The number of facets to return starting from the offset.
-             * @return a list of facet entries to be rendered based on the specified offset and limit
-             */
+            /// <summary>
+            /// Returns a list of facet entries to be rendered based on the specified offset and limit.
+            /// The facet entries are retrieved from the facet entries collected during merging.
+            /// </summary>
+            /// <param name="offset">The offset in the collected facet entries during merging</param>
+            /// <param name="limit">The number of facets to return starting from the offset.</param>
+            /// <returns>a list of facet entries to be rendered based on the specified offset and limit</returns>
             public List<FacetEntry> GetFacetEntries(int offset, int limit)
             {
                 List<FacetEntry> entries = new List<FacetEntry>();
@@ -205,11 +222,9 @@ namespace Lucene.Net.Search.Grouping
                 return entries;
             }
 
-            /**
-             * Returns the sum of all facet entries counts.
-             *
-             * @return the sum of all facet entries counts
-             */
+            /// <summary>
+            /// Gets the sum of all facet entries counts.
+            /// </summary>
             public int TotalCount
             {
                 get
@@ -218,11 +233,9 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-            /**
-             * Returns the number of groups that didn't have a facet value.
-             *
-             * @return the number of groups that didn't have a facet value
-             */
+            /// <summary>
+            /// Gets the number of groups that didn't have a facet value.
+            /// </summary>
             public int TotalMissingCount
             {
                 get
@@ -232,9 +245,9 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        /**
-         * Represents a facet entry with a value and a count.
-         */
+        /// <summary>
+        /// Represents a facet entry with a value and a count.
+        /// </summary>
         public class FacetEntry
         {
 
@@ -275,9 +288,9 @@ namespace Lucene.Net.Search.Grouping
                     '}';
             }
 
-            /**
-             * @return The value of this facet entry
-             */
+            /// <summary>
+            /// Gets the value of this facet entry
+            /// </summary>
             public BytesRef Value
             {
                 get
@@ -286,9 +299,9 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-            /**
-             * @return The count (number of groups) of this facet entry.
-             */
+            /// <summary>
+            /// Gets the count (number of groups) of this facet entry.
+            /// </summary>
             public int Count
             {
                 get
@@ -298,10 +311,14 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        /**
-         * Contains the local grouped segment counts for a particular segment.
-         * Each <code>SegmentResult</code> must be added together.
-         */
+        /// <summary>
+        /// Contains the local grouped segment counts for a particular segment.
+        /// Each <see cref="AbstractSegmentResult"/> must be added together.
+        /// </summary>
+        /// <remarks>
+        /// LUCENENET NOTE: Renamed from SegmentResult to AbstractSegmentResult
+        /// to avoid naming conflicts with subclasses.
+        /// </remarks>
         protected internal abstract class AbstractSegmentResult
         {
             protected internal readonly int[] counts;
@@ -320,11 +337,10 @@ namespace Lucene.Net.Search.Grouping
                 this.maxTermPos = maxTermPos;
             }
 
-            /**
-             * Go to next term in this <code>SegmentResult</code> in order to retrieve the grouped facet counts.
-             *
-             * @throws IOException If I/O related errors occur
-             */
+            /// <summary>
+            /// Go to next term in this <see cref="AbstractSegmentResult"/> in order to retrieve the grouped facet counts.
+            /// </summary>
+            /// <exception cref="IOException">If I/O related errors occur</exception>
             protected internal abstract void NextTerm();
 
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
index de3feb6..e8aedc8 100644
--- a/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractSecondPassGroupingCollector.cs
@@ -6,6 +6,23 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// SecondPassGroupingCollector is the second of two passes
     /// necessary to collect grouped docs.  This pass gathers the
@@ -13,7 +30,7 @@ namespace Lucene.Net.Search.Grouping
     /// first pass. Concrete subclasses define what a group is and how it
     /// is internally collected.
     /// <para>
-    /// See {@link org.apache.lucene.search.grouping} for more
+    /// See <a href="https://github.com/apache/lucene-solr/blob/releases/lucene-solr/4.8.0/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html">org.apache.lucene.search.grouping</a> for more
     /// details including a full code example.
     /// </para>
     /// @lucene.experimental
@@ -87,13 +104,12 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        /**
-         * Returns the group the specified doc belongs to or <code>null</code> if no group could be retrieved.
-         *
-         * @param doc The specified doc
-         * @return the group the specified doc belongs to or <code>null</code> if no group could be retrieved
-         * @throws IOException If an I/O related error occurred
-         */
+        /// <summary>
+        /// Returns the group the specified doc belongs to or <c>null</c> if no group could be retrieved.
+        /// </summary>
+        /// <param name="doc">The specified doc</param>
+        /// <returns>the group the specified doc belongs to or <c>null</c> if no group could be retrieved</returns>
+        /// <exception cref="IOException">If an I/O related error occurred</exception>
         protected abstract AbstractSecondPassGroupingCollector.SearchGroupDocs<TGroupValue> RetrieveGroup(int doc);
 
         public override AtomicReaderContext NextReader
@@ -142,6 +158,11 @@ namespace Lucene.Net.Search.Grouping
         
     }
 
+    /// <summary>
+    /// LUCENENET specific class used to simulate the syntax used 
+    /// to access nested classes of <see cref="AbstractAllGroupHeadsCollector{GH}"/>
+    /// without referencing the generic closing type.
+    /// </summary>
     public class AbstractSecondPassGroupingCollector
     {
         /// <summary>
@@ -166,6 +187,7 @@ namespace Lucene.Net.Search.Grouping
 
     /// <summary>
     /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// to simulate Java's wildcard generics.
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
     public interface IAbstractSecondPassGroupingCollector<out TGroupValue>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
index c7fd34c..0f3549f 100644
--- a/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/BlockGroupingCollector.cs
@@ -6,6 +6,23 @@ using System.Diagnostics;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     // TODO: this sentence is too long for the class summary.
     /// <summary>
     /// BlockGroupingCollector performs grouping with a
@@ -32,7 +49,7 @@ namespace Lucene.Net.Search.Grouping
     /// you to ensure this was the case.
     /// </para>
     /// <para>
-    /// See {@link org.apache.lucene.search.grouping} for more
+    /// See <a href="https://github.com/apache/lucene-solr/blob/releases/lucene-solr/4.8.0/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html">org.apache.lucene.search.grouping</a> for more
     /// details including a full code example.
     /// </para>
     /// @lucene.experimental
@@ -247,24 +264,28 @@ namespace Lucene.Net.Search.Grouping
             subDocUpto = 0;
         }
 
-        /**
-         * Create the single pass collector.
-         *
-         *  @param groupSort The {@link Sort} used to sort the
-         *    groups.  The top sorted document within each group
-         *    according to groupSort, determines how that group
-         *    sorts against other groups.  This must be non-null,
-         *    ie, if you want to groupSort by relevance use
-         *    Sort.RELEVANCE.
-         *  @param topNGroups How many top groups to keep.
-         *  @param needsScores true if the collected documents
-         *    require scores, either because relevance is included
-         *    in the withinGroupSort or because you plan to pass true
-         *    for either getSscores or getMaxScores to {@link
-         *    #getTopGroups}
-         *  @param lastDocPerGroup a {@link Filter} that marks the
-         *    last document in each group.
-         */
+        /// <summary>
+        /// Create the single pass collector.
+        /// </summary>
+        /// <param name="groupSort">
+        /// The <see cref="Sort"/> used to sort the
+        /// groups.  The top sorted document within each group
+        /// according to groupSort, determines how that group
+        /// sorts against other groups.  This must be non-null,
+        /// ie, if you want to groupSort by relevance use
+        /// <see cref="Sort.RELEVANCE"/>.
+        /// </param>
+        /// <param name="topNGroups">How many top groups to keep.</param>
+        /// <param name="needsScores">
+        /// true if the collected documents
+        /// require scores, either because relevance is included
+        /// in the withinGroupSort or because you plan to pass true
+        /// for either GetScores or GetMaxScores to <see cref="GetTopGroups(Sort, int, int, int, bool)"/>
+        /// </param>
+        /// <param name="lastDocPerGroup">
+        /// a <see cref="Filter"/> that marks the
+        /// last document in each group.
+        /// </param>
         public BlockGroupingCollector(Sort groupSort, int topNGroups, bool needsScores, Filter lastDocPerGroup)
         {
 
@@ -305,32 +326,68 @@ namespace Lucene.Net.Search.Grouping
         // typically they will be presented as a "single" result
         // in the UI?
 
-        /** Returns the grouped results.  Returns null if the
-         *  number of groups collected is <= groupOffset.
-         *
-         *  <p><b>NOTE</b>: This collector is unable to compute
-         *  the groupValue per group so it will always be null.
-         *  This is normally not a problem, as you can obtain the
-         *  value just like you obtain other values for each
-         *  matching document (eg, via stored fields, via
-         *  FieldCache, etc.)
-         *
-         *  @param withinGroupSort The {@link Sort} used to sort
-         *    documents within each group.  Passing null is
-         *    allowed, to sort by relevance.
-         *  @param groupOffset Which group to start from
-         *  @param withinGroupOffset Which document to start from
-         *    within each group
-         *  @param maxDocsPerGroup How many top documents to keep
-         *     within each group.
-         *  @param fillSortFields If true then the Comparable
-         *     values for the sort fields will be set
-         */
+        /// <summary>
+        /// Returns the grouped results.  Returns null if the
+        /// number of groups collected is &lt;= groupOffset.
+        /// 
+        /// <para>
+        /// <b>NOTE</b>: This collector is unable to compute
+        /// the groupValue per group so it will always be null.
+        /// This is normally not a problem, as you can obtain the
+        /// value just like you obtain other values for each
+        /// matching document (eg, via stored fields, via
+        /// FieldCache, etc.)
+        /// </para>
+        /// </summary>
+        /// <param name="withinGroupSort">
+        /// The <see cref="Sort"/> used to sort
+        /// documents within each group.  Passing null is
+        /// allowed, to sort by relevance.
+        /// </param>
+        /// <param name="groupOffset">Which group to start from</param>
+        /// <param name="withinGroupOffset">
+        /// Which document to start from within each group
+        /// </param>
+        /// <param name="maxDocsPerGroup">
+        /// How many top documents to keep within each group.
+        /// </param>
+        /// <param name="fillSortFields">
+        /// If true then the Comparable values for the sort fields will be set
+        /// </param>
         public ITopGroups<object> GetTopGroups(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
         {
             return GetTopGroups<object>(withinGroupSort, groupOffset, withinGroupOffset, maxDocsPerGroup, fillSortFields);
         }
 
+        /// <summary>
+        /// Returns the grouped results.  Returns null if the
+        /// number of groups collected is &lt;= groupOffset.
+        /// 
+        /// <para>
+        /// <b>NOTE</b>: This collector is unable to compute
+        /// the groupValue per group so it will always be null.
+        /// This is normally not a problem, as you can obtain the
+        /// value just like you obtain other values for each
+        /// matching document (eg, via stored fields, via
+        /// FieldCache, etc.)
+        /// </para>
+        /// </summary>
+        /// <typeparam name="TGroupValue">The expected return type for group value</typeparam>
+        /// <<param name="withinGroupSort">
+        /// The <see cref="Sort"/> used to sort
+        /// documents within each group.  Passing null is
+        /// allowed, to sort by relevance.
+        /// </param>
+        /// <param name="groupOffset">Which group to start from</param>
+        /// <param name="withinGroupOffset">
+        /// Which document to start from within each group
+        /// </param>
+        /// <param name="maxDocsPerGroup">
+        /// How many top documents to keep within each group.
+        /// </param>
+        /// <param name="fillSortFields">
+        /// If true then the Comparable values for the sort fields will be set
+        /// </param>
         public ITopGroups<TGroupValue> GetTopGroups<TGroupValue>(Sort withinGroupSort, int groupOffset, int withinGroupOffset, int maxDocsPerGroup, bool fillSortFields)
         {
 
@@ -595,7 +652,6 @@ namespace Lucene.Net.Search.Grouping
                 {
                     comparators[i] = comparators[i].SetNextReader(value);
                 }
-
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
index 51a905f..39e0d92 100644
--- a/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
+++ b/src/Lucene.Net.Grouping/CollectedSearchGroup.cs
@@ -1,8 +1,25 @@
 \ufeffnamespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
-    /// Expert: representation of a group in {@link AbstractFirstPassGroupingCollector},
-    /// tracking the top doc and {@link FieldComparator} slot.
+    /// Expert: representation of a group in <see cref="AbstractFirstPassGroupingCollector{TGroupValue}"/>,
+    /// tracking the top doc and <see cref="FieldComparator"/> slot.
     /// @lucene.internal
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
index 70aa484..70a2033 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
@@ -6,6 +6,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Function
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// An implementation of <see cref="AbstractAllGroupHeadsCollector"/> for retrieving the most relevant groups when grouping
     /// by <see cref="ValueSource"/>.
@@ -24,13 +41,12 @@ namespace Lucene.Net.Search.Grouping.Function
         private AtomicReaderContext readerContext;
         private Scorer scorer;
 
-        /**
-         * Constructs a {@link FunctionAllGroupHeadsCollector} instance.
-         *
-         * @param groupBy The {@link ValueSource} to group by
-         * @param vsContext The ValueSource context
-         * @param sortWithinGroup The sort within a group
-         */
+        /// <summary>
+        /// Constructs a <see cref="FunctionAllGroupHeadsCollector"/> instance.
+        /// </summary>
+        /// <param name="groupBy">The <see cref="ValueSource"/> to group by</param>
+        /// <param name="vsContext">The <see cref="ValueSource"/> context</param>
+        /// <param name="sortWithinGroup">The sort within a group</param>
         public FunctionAllGroupHeadsCollector(ValueSource groupBy, IDictionary /* Map<?, ?> */ vsContext, Sort sortWithinGroup)
             : base(sortWithinGroup.GetSort().Length)
         {
@@ -103,9 +119,11 @@ namespace Lucene.Net.Search.Grouping.Function
             }
         }
 
-        /** Holds current head document for a single group.
-         *
-         * @lucene.experimental */
+        /// <summary>
+        /// Holds current head document for a single group.
+        /// 
+        /// @lucene.experimental
+        /// </summary>
         public class GroupHead : AbstractAllGroupHeadsCollector_GroupHead
         {
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
index c5c7623..be73a9a 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupsCollector.cs
@@ -6,6 +6,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Function
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// A collector that collects all groups that match the
     /// query. Only the group value is collected, and the order
@@ -27,12 +44,11 @@ namespace Lucene.Net.Search.Grouping.Function
         private FunctionValues.AbstractValueFiller filler;
         private MutableValue mval;
 
-        /**
-         * Constructs a {@link FunctionAllGroupsCollector} instance.
-         *
-         * @param groupBy The {@link ValueSource} to group by
-         * @param vsContext The ValueSource context
-         */
+        /// <summary>
+        /// Constructs a <see cref="FunctionAllGroupsCollector"/> instance.
+        /// </summary>
+        /// <param name="groupBy">The <see cref="ValueSource"/> to group by</param>
+        /// <param name="vsContext">The <see cref="ValueSource"/> context</param>
         public FunctionAllGroupsCollector(ValueSource groupBy, IDictionary /* Map<?, ?> */ vsContext)
         {
             this.vsContext = vsContext;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
index 22f2395..409cc67 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionDistinctValuesCollector.cs
@@ -7,6 +7,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Function
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Function based implementation of <see cref="AbstractDistinctValuesCollector"/>.
     /// 
@@ -65,11 +82,11 @@ namespace Lucene.Net.Search.Grouping.Function
             }
         }
 
-
-
-        /** Holds distinct values for a single group.
-         *
-         * @lucene.experimental */
+        /// <summary>
+        /// Holds distinct values for a single group.
+        /// 
+        /// @lucene.experimental
+        /// </summary>
         public class GroupCount : AbstractDistinctValuesCollector.GroupCount<MutableValue>
         {
             internal GroupCount(MutableValue groupValue)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
index 18f9fb6..fcf102d 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionFirstPassGroupingCollector.cs
@@ -5,6 +5,23 @@ using System.Collections;
 
 namespace Lucene.Net.Search.Grouping.Function
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Concrete implementation of <see cref="AbstractFirstPassGroupingCollector{TGroupValue}"/> that groups based on
     /// <see cref="ValueSource"/> instances.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
index ec1fccb..027ea55 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionSecondPassGroupingCollector.cs
@@ -6,6 +6,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping.Function
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Concrete implementation of <see cref="AbstractSecondPassGroupingCollector{TGroupValue}"/> that groups based on
     /// <see cref="ValueSource"/> instances.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/GroupDocs.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupDocs.cs b/src/Lucene.Net.Grouping/GroupDocs.cs
index cc1a7c6..c997e30 100644
--- a/src/Lucene.Net.Grouping/GroupDocs.cs
+++ b/src/Lucene.Net.Grouping/GroupDocs.cs
@@ -71,6 +71,7 @@ namespace Lucene.Net.Search.Grouping
 
     /// <summary>
     /// LUCENENET specific interface used to apply covariance to TGroupValue
+    /// to simulate Java's wildcard generics.
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
     public interface IGroupDocs<out TGroupValue>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/GroupingSearch.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/GroupingSearch.cs b/src/Lucene.Net.Grouping/GroupingSearch.cs
index c9353d8..5bb98c5 100644
--- a/src/Lucene.Net.Grouping/GroupingSearch.cs
+++ b/src/Lucene.Net.Grouping/GroupingSearch.cs
@@ -9,6 +9,23 @@ using System.Collections.Generic;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Convenience class to perform grouping in a non distributed environment.
     /// @lucene.experimental
@@ -39,36 +56,33 @@ namespace Lucene.Net.Search.Grouping
         private ICollection /* Collection<?> */ matchingGroups;
         private Bits matchingGroupHeads;
 
-        /**
-         * Constructs a <code>GroupingSearch</code> instance that groups documents by index terms using the {@link FieldCache}.
-         * The group field can only have one token per document. This means that the field must not be analysed.
-         *
-         * @param groupField The name of the field to group by.
-         */
+        /// <summary>
+        /// Constructs a <see cref="GroupingSearch"/> instance that groups documents by index terms using the <see cref="FieldCache"/>.
+        /// The group field can only have one token per document. This means that the field must not be analysed.
+        /// </summary>
+        /// <param name="groupField">The name of the field to group by.</param>
         public GroupingSearch(string groupField)
             : this(groupField, null, null, null)
         {
         }
 
-        /**
-         * Constructs a <code>GroupingSearch</code> instance that groups documents by function using a {@link ValueSource}
-         * instance.
-         *
-         * @param groupFunction      The function to group by specified as {@link ValueSource}
-         * @param valueSourceContext The context of the specified groupFunction
-         */
+        /// <summary>
+        /// Constructs a <see cref="GroupingSearch"/> instance that groups documents by function using a <see cref="ValueSource"/>
+        /// instance.
+        /// </summary>
+        /// <param name="groupFunction">The function to group by specified as <see cref="ValueSource"/></param>
+        /// <param name="valueSourceContext">The context of the specified groupFunction</param>
         public GroupingSearch(ValueSource groupFunction, IDictionary /* Map<?, ?> */ valueSourceContext)
             : this(null, groupFunction, valueSourceContext, null)
         {
 
         }
 
-        /**
-         * Constructor for grouping documents by doc block.
-         * This constructor can only be used when documents belonging in a group are indexed in one block.
-         *
-         * @param groupEndDocs The filter that marks the last document in all doc blocks
-         */
+        /// <summary>
+        /// Constructor for grouping documents by doc block.
+        /// This constructor can only be used when documents belonging in a group are indexed in one block.
+        /// </summary>
+        /// <param name="groupEndDocs">The filter that marks the last document in all doc blocks</param>
         public GroupingSearch(Filter groupEndDocs)
             : this(null, null, null, groupEndDocs)
         {
@@ -82,37 +96,46 @@ namespace Lucene.Net.Search.Grouping
             this.groupEndDocs = groupEndDocs;
         }
 
-        /**
-         * Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
-         *
-         * @param searcher    The {@link org.apache.lucene.search.IndexSearcher} instance to execute the grouped search on.
-         * @param query       The query to execute with the grouping
-         * @param groupOffset The group offset
-         * @param groupLimit  The number of groups to return from the specified group offset
-         * @return the grouped result as a {@link TopGroups} instance
-         * @throws IOException If any I/O related errors occur
-         */
+        /// <summary>
+        /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
+        /// </summary>
+        /// <param name="searcher">The <see cref="IndexSearcher"/> instance to execute the grouped search on.</param>
+        /// <param name="query">The query to execute with the grouping</param>
+        /// <param name="groupOffset">The group offset</param>
+        /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
+        /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
+        /// <exception cref="IOException">If any I/O related errors occur</exception>
         public ITopGroups<object> Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
         {
             return Search<object>(searcher, null, query, groupOffset, groupLimit);
         }
 
+
+        /// <summary>
+        /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
+        /// </summary>
+        /// <typeparam name="TGroupValue">The expected return type of the search.</typeparam>
+        /// <param name="searcher">The <see cref="IndexSearcher"/> instance to execute the grouped search on.</param>
+        /// <param name="query">The query to execute with the grouping</param>
+        /// <param name="groupOffset">The group offset</param>
+        /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
+        /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
+        /// <exception cref="IOException">If any I/O related errors occur</exception>
         public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
         {
             return Search<TGroupValue>(searcher, null, query, groupOffset, groupLimit);
         }
 
-        /**
-         * Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
-         *
-         * @param searcher    The {@link org.apache.lucene.search.IndexSearcher} instance to execute the grouped search on.
-         * @param filter      The filter to execute with the grouping
-         * @param query       The query to execute with the grouping
-         * @param groupOffset The group offset
-         * @param groupLimit  The number of groups to return from the specified group offset
-         * @return the grouped result as a {@link TopGroups} instance
-         * @throws IOException If any I/O related errors occur
-         */
+        /// <summary>
+        /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
+        /// </summary>
+        /// <param name="searcher">The <see cref="IndexSearcher"/> instance to execute the grouped search on.</param>
+        /// <param name="filter">The filter to execute with the grouping</param>
+        /// <param name="query">The query to execute with the grouping</param>
+        /// <param name="groupOffset">The group offset</param>
+        /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
+        /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
+        /// <exception cref="IOException">If any I/O related errors occur</exception>
         public ITopGroups<object> Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             if (groupFunction != null)
@@ -133,6 +156,17 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
+        /// <summary>
+        /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
+        /// </summary>
+        /// <typeparam name="TGroupValue">The expected return type of the search.</typeparam>
+        /// <param name="searcher">The <see cref="IndexSearcher"/> instance to execute the grouped search on.</param>
+        /// <param name="filter">The filter to execute with the grouping</param>
+        /// <param name="query">The query to execute with the grouping</param>
+        /// <param name="groupOffset">The group offset</param>
+        /// <param name="groupLimit">The number of groups to return from the specified group offset</param>
+        /// <returns>the grouped result as a <see cref="ITopGroups{Object}"/> instance</returns>
+        /// <exception cref="IOException">If any I/O related errors occur</exception>
         public ITopGroups<TGroupValue> Search<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             if (groupField != null || groupFunction != null)
@@ -149,19 +183,6 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        //protected ITopGroups<object> GroupByFieldOrFunction(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
-        //{
-        //    // LUCENENET TODO: Perhaps there is a better way to infer type without resorting to hard-coding them here, but
-        //    // the original GroupByFieldOrFunction is already aware of the underlying type based on the FirstPassGroupingCollector
-        //    // and SecondPassGroupingCollector.
-        //    if (groupFunction != null)
-        //    {
-        //        return GroupByFieldOrFunction<MutableValue>(searcher, filter, query, groupOffset, groupLimit);
-        //    }
-
-        //    return GroupByFieldOrFunction<BytesRef>(searcher, filter, query, groupOffset, groupLimit);
-        //}
-
         protected ITopGroups<TGroupValue> GroupByFieldOrFunction<TGroupValue>(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
         {
             int topN = groupOffset + groupLimit;
@@ -323,15 +344,14 @@ namespace Lucene.Net.Search.Grouping
             return c.GetTopGroups<TGroupValue>(sortWithinGroup, groupOffset, groupDocsOffset, topNInsideGroup, fillSortFields);
         }
 
-        /**
-         * Enables caching for the second pass search. The cache will not grow over a specified limit in MB.
-         * The cache is filled during the first pass searched and then replayed during the second pass searched.
-         * If the cache grows beyond the specified limit, then the cache is purged and not used in the second pass search.
-         *
-         * @param maxCacheRAMMB The maximum amount in MB the cache is allowed to hold
-         * @param cacheScores   Whether to cache the scores
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Enables caching for the second pass search. The cache will not grow over a specified limit in MB.
+        /// The cache is filled during the first pass searched and then replayed during the second pass searched.
+        /// If the cache grows beyond the specified limit, then the cache is purged and not used in the second pass search.
+        /// </summary>
+        /// <param name="maxCacheRAMMB">The maximum amount in MB the cache is allowed to hold</param>
+        /// <param name="cacheScores">Whether to cache the scores</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheScores)
         {
             this.maxCacheRAMMB = maxCacheRAMMB;
@@ -340,15 +360,14 @@ namespace Lucene.Net.Search.Grouping
             return this;
         }
 
-        /**
-         * Enables caching for the second pass search. The cache will not contain more than the maximum specified documents.
-         * The cache is filled during the first pass searched and then replayed during the second pass searched.
-         * If the cache grows beyond the specified limit, then the cache is purged and not used in the second pass search.
-         *
-         * @param maxDocsToCache The maximum number of documents the cache is allowed to hold
-         * @param cacheScores    Whether to cache the scores
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Enables caching for the second pass search. The cache will not contain more than the maximum specified documents.
+        /// The cache is filled during the first pass searched and then replayed during the second pass searched.
+        /// If the cache grows beyond the specified limit, then the cache is purged and not used in the second pass search.
+        /// </summary>
+        /// <param name="maxDocsToCache">The maximum number of documents the cache is allowed to hold</param>
+        /// <param name="cacheScores">Whether to cache the scores</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
         {
             this.maxDocsToCache = maxDocsToCache;
@@ -357,11 +376,10 @@ namespace Lucene.Net.Search.Grouping
             return this;
         }
 
-        /**
-         * Disables any enabled cache.
-         *
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Disables any enabled cache.
+        /// </summary>
+        /// <returns><c>this</c></returns>
         public GroupingSearch DisableCaching()
         {
             this.maxCacheRAMMB = null;
@@ -369,163 +387,162 @@ namespace Lucene.Net.Search.Grouping
             return this;
         }
 
-        /**
-         * Specifies how groups are sorted.
-         * Defaults to {@link Sort#RELEVANCE}.
-         *
-         * @param groupSort The sort for the groups.
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Specifies how groups are sorted.
+        /// Defaults to <see cref="Sort.RELEVANCE"/>.
+        /// </summary>
+        /// <param name="groupSort">The sort for the groups.</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetGroupSort(Sort groupSort)
         {
             this.groupSort = groupSort;
             return this;
         }
 
-        /**
-         * Specified how documents inside a group are sorted.
-         * Defaults to {@link Sort#RELEVANCE}.
-         *
-         * @param sortWithinGroup The sort for documents inside a group
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Specified how documents inside a group are sorted.
+        /// Defaults to <see cref="Sort.RELEVANCE"/>.
+        /// </summary>
+        /// <param name="sortWithinGroup">The sort for documents inside a group</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
         {
             this.sortWithinGroup = sortWithinGroup;
             return this;
         }
 
-        /**
-         * Specifies the offset for documents inside a group.
-         *
-         * @param groupDocsOffset The offset for documents inside a
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Specifies the offset for documents inside a group.
+        /// </summary>
+        /// <param name="groupDocsOffset">The offset for documents inside a</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetGroupDocsOffset(int groupDocsOffset)
         {
             this.groupDocsOffset = groupDocsOffset;
             return this;
         }
 
-        /**
-         * Specifies the number of documents to return inside a group from the specified groupDocsOffset.
-         *
-         * @param groupDocsLimit The number of documents to return inside a group
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Specifies the number of documents to return inside a group from the specified groupDocsOffset.
+        /// </summary>
+        /// <param name="groupDocsLimit">The number of documents to return inside a group</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetGroupDocsLimit(int groupDocsLimit)
         {
             this.groupDocsLimit = groupDocsLimit;
             return this;
         }
 
-        /**
-         * Whether to also fill the sort fields per returned group and groups docs.
-         *
-         * @param fillSortFields Whether to also fill the sort fields per returned group and groups docs
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Whether to also fill the sort fields per returned group and groups docs.
+        /// </summary>
+        /// <param name="fillSortFields">Whether to also fill the sort fields per returned group and groups docs</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetFillSortFields(bool fillSortFields)
         {
             this.fillSortFields = fillSortFields;
             return this;
         }
 
-        /**
-         * Whether to include the scores per doc inside a group.
-         *
-         * @param includeScores Whether to include the scores per doc inside a group
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Whether to include the scores per doc inside a group.
+        /// </summary>
+        /// <param name="includeScores">Whether to include the scores per doc inside a group</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetIncludeScores(bool includeScores)
         {
             this.includeScores = includeScores;
             return this;
         }
 
-        /**
-         * Whether to include the score of the most relevant document per group.
-         *
-         * @param includeMaxScore Whether to include the score of the most relevant document per group
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Whether to include the score of the most relevant document per group.
+        /// </summary>
+        /// <param name="includeMaxScore">Whether to include the score of the most relevant document per group</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetIncludeMaxScore(bool includeMaxScore)
         {
             this.includeMaxScore = includeMaxScore;
             return this;
         }
 
-        /**
-         * Whether to also compute all groups matching the query.
-         * This can be used to determine the number of groups, which can be used for accurate pagination.
-         * <p/>
-         * When grouping by doc block the number of groups are automatically included in the {@link TopGroups} and this
-         * option doesn't have any influence.
-         *
-         * @param allGroups to also compute all groups matching the query
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Whether to also compute all groups matching the query.
+        /// This can be used to determine the number of groups, which can be used for accurate pagination.
+        /// <para>
+        /// When grouping by doc block the number of groups are automatically included in the <see cref="TopGroups"/> and this
+        /// option doesn't have any influence.
+        /// </para>
+        /// </summary>
+        /// <param name="allGroups">to also compute all groups matching the query</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetAllGroups(bool allGroups)
         {
             this.allGroups = allGroups;
             return this;
         }
 
-        /**
-         * If {@link #setAllGroups(boolean)} was set to <code>true</code> then all matching groups are returned, otherwise
-         * an empty collection is returned.
-         *
-         * @param <T> The group value type. This can be a {@link BytesRef} or a {@link MutableValue} instance. If grouping
-         *            by doc block this the group value is always <code>null</code>.
-         * @return all matching groups are returned, or an empty collection
-         */
+        /// <summary>
+        /// If <see cref="SetAllGroups(bool)"/> was set to <c>true</c> then all matching groups are returned, otherwise
+        /// an empty collection is returned.
+        /// </summary>
+        /// <typeparam name="T">The group value type. This can be a <see cref="BytesRef"/> or a <see cref="MutableValue"/> instance. 
+        /// If grouping by doc block this the group value is always <c>null</c>.</typeparam>
+        /// <returns>all matching groups are returned, or an empty collection</returns>
         public ICollection<T> GetAllMatchingGroups<T>()
         {
             return (ICollection<T>)matchingGroups;
         }
 
-        // LUCENENET specific used to get the groups if the type is unknown (since the above
-        // method will crash if the wrong type is used)
+        /// <summary>
+        /// If <see cref="SetAllGroups(bool)"/> was set to <c>true</c> then all matching groups are returned, otherwise
+        /// an empty collection is returned.
+        /// </summary>
+        /// <returns>all matching groups are returned, or an empty collection</returns>
+        /// <remarks>
+        /// LUCENENET specific used to get the groups if the type is unknown or if the code expects
+        /// any type, since <see cref="GetAllMatchingGroups{T}"/>
+        /// will throw an exception if the return type is incorrect.
+        /// </remarks>
         public ICollection GetAllMatchingGroups()
         {
             return matchingGroups;
         }
 
-        /**
-         * Whether to compute all group heads (most relevant document per group) matching the query.
-         * <p/>
-         * This feature isn't enabled when grouping by doc block.
-         *
-         * @param allGroupHeads Whether to compute all group heads (most relevant document per group) matching the query
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Whether to compute all group heads (most relevant document per group) matching the query.
+        /// <para>
+        /// This feature isn't enabled when grouping by doc block.
+        /// </para>
+        /// </summary>
+        /// <param name="allGroupHeads">Whether to compute all group heads (most relevant document per group) matching the query</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetAllGroupHeads(bool allGroupHeads)
         {
             this.allGroupHeads = allGroupHeads;
             return this;
         }
 
-        /**
-         * Returns the matching group heads if {@link #setAllGroupHeads(boolean)} was set to true or an empty bit set.
-         *
-         * @return The matching group heads if {@link #setAllGroupHeads(boolean)} was set to true or an empty bit set
-         */
+        /// <summary>
+        /// Returns the matching group heads if <see cref="SetAllGroupHeads(bool)"/> was set to true or an empty bit set.
+        /// </summary>
+        /// <returns>The matching group heads if <see cref="SetAllGroupHeads(bool)"/> was set to true or an empty bit set</returns>
         public Bits GetAllGroupHeads()
         {
             return matchingGroupHeads;
         }
 
-        /**
-         * Sets the initial size of some internal used data structures.
-         * This prevents growing data structures many times. This can improve the performance of the grouping at the cost of
-         * more initial RAM.
-         * <p/>
-         * The {@link #setAllGroups} and {@link #setAllGroupHeads} features use this option.
-         * Defaults to 128.
-         *
-         * @param initialSize The initial size of some internal used data structures
-         * @return <code>this</code>
-         */
+        /// <summary>
+        /// Sets the initial size of some internal used data structures.
+        /// This prevents growing data structures many times. This can improve the performance of the grouping at the cost of
+        /// more initial RAM.
+        /// <para>
+        /// The <see cref="SetAllGroups(bool)"/> and <see cref="SetAllGroupHeads(bool)"/> features use this option.
+        /// Defaults to 128.
+        /// </para>
+        /// </summary>
+        /// <param name="initialSize">The initial size of some internal used data structures</param>
+        /// <returns><c>this</c></returns>
         public GroupingSearch SetInitialSize(int initialSize)
         {
             this.initialSize = initialSize;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0a61e24/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index 23140bc..bbf2082 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -6,21 +6,43 @@ using System.Linq;
 
 namespace Lucene.Net.Search.Grouping
 {
+    /*
+	 * 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.
+	 */
+
     /// <summary>
     /// Represents a group that is found during the first pass search.
+    /// 
     /// @lucene.experimental
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
     public class SearchGroup<TGroupValue> : ISearchGroup<TGroupValue>
     {
-        /** The value that defines this group  */
+        /// <summary>
+        /// The value that defines this group 
+        /// </summary>
         public TGroupValue GroupValue { get; set; }
 
-        /** The sort values used during sorting. These are the
-         *  groupSort field values of the highest rank document
-         *  (by the groupSort) within the group.  Can be
-         * <code>null</code> if <code>fillFields=false</code> had
-         * been passed to {@link AbstractFirstPassGroupingCollector#getTopGroups} */
+        /// <summary>
+        /// The sort values used during sorting. These are the
+        /// groupSort field values of the highest rank document
+        /// (by the groupSort) within the group.  Can be
+        /// <c>null</c> if <c>fillFields=false</c> had
+        /// been passed to <see cref="AbstractFirstPassGroupingCollector{TGroupValue}.GetTopGroups(int, bool)"/>
+        /// </summary>
         public object[] SortValues { get; set; }
 
         public override string ToString()
@@ -96,7 +118,10 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        // Holds all shards currently on the same group
+        /// <summary>
+        /// Holds all shards currently on the same group
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
         private class MergedGroup<T>
         {
 
@@ -373,16 +398,17 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-
-        /** Merges multiple collections of top groups, for example
-         *  obtained from separate index shards.  The provided
-         *  groupSort must match how the groups were sorted, and
-         *  the provided SearchGroups must have been computed
-         *  with fillFields=true passed to {@link
-         *  AbstractFirstPassGroupingCollector#getTopGroups}.
-         *
-         * <p>NOTE: this returns null if the topGroups is empty.
-         */
+        /// <summary>
+        /// Merges multiple collections of top groups, for example
+        /// obtained from separate index shards.  The provided
+        /// groupSort must match how the groups were sorted, and
+        /// the provided SearchGroups must have been computed
+        /// with <c>fillFields=true</c> passed to
+        /// <see cref="AbstractFirstPassGroupingCollector{TGroupValue}.GetTopGroups(int, bool)"/>.
+        /// <para>
+        /// NOTE: this returns null if the topGroups is empty.
+        /// </para>
+        /// </summary>
         public static ICollection<SearchGroup<T>> Merge<T>(IList<IEnumerable<ISearchGroup<T>>> topGroups, int offset, int topN, Sort groupSort)
         {
             if (topGroups.Count == 0)
@@ -399,12 +425,23 @@ namespace Lucene.Net.Search.Grouping
 
     /// <summary>
     /// LUCENENET specific interface used to provide covariance
-    /// with the TGroupValue type
+    /// with the TGroupValue type to simulate Java's wildcard generics.
     /// </summary>
     /// <typeparam name="TGroupValue"></typeparam>
     public interface ISearchGroup<out TGroupValue>
     {
+        /// <summary>
+        /// The value that defines this group 
+        /// </summary>
         TGroupValue GroupValue { get; }
+
+        /// <summary>
+        /// The sort values used during sorting. These are the
+        /// groupSort field values of the highest rank document
+        /// (by the groupSort) within the group.  Can be
+        /// <c>null</c> if <c>fillFields=false</c> had
+        /// been passed to <see cref="AbstractFirstPassGroupingCollector{TGroupValue}.GetTopGroups(int, bool)"/>
+        /// </summary>
         object[] SortValues { get; set; }
     }
 }


[55/58] [abbrv] lucenenet git commit: Grouping refactor: AbstractAllGroupHeadsCollector.GetCollectedGroupHeads() -> CollectedGroupHeads (property)

Posted by ni...@apache.org.
Grouping refactor: AbstractAllGroupHeadsCollector.GetCollectedGroupHeads() -> CollectedGroupHeads (property)


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

Branch: refs/heads/grouping
Commit: 04f4013d8304d1809238b99a01cec2c65bbe6e82
Parents: 049718c
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Mon Nov 7 22:43:55 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:48:34 2016 +0700

----------------------------------------------------------------------
 .../AbstractAllGroupHeadsCollector.cs               |  8 ++++----
 .../Function/FunctionAllGroupHeadsCollector.cs      |  4 ++--
 .../Term/TermAllGroupHeadsCollector.cs              | 16 ++++++++--------
 3 files changed, 14 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/04f4013d/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
index bf3d984..190fb82 100644
--- a/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/AbstractAllGroupHeadsCollector.cs
@@ -49,7 +49,7 @@ namespace Lucene.Net.Search.Grouping
         {
             FixedBitSet bitSet = new FixedBitSet(maxDoc);
 
-            ICollection<GH> groupHeads = GetCollectedGroupHeads();
+            ICollection<GH> groupHeads = CollectedGroupHeads;
             foreach (GH groupHead in groupHeads)
             {
                 bitSet.Set(groupHead.Doc);
@@ -64,7 +64,7 @@ namespace Lucene.Net.Search.Grouping
         /// <returns>an int array containing all group heads. The size of the array is equal to number of collected unique groups.</returns>
         public override int[] RetrieveGroupHeads()
         {
-            ICollection<GH> groupHeads = GetCollectedGroupHeads();
+            ICollection<GH> groupHeads = CollectedGroupHeads;
             int[] docHeads = new int[groupHeads.Count];
 
             int i = 0;
@@ -84,7 +84,7 @@ namespace Lucene.Net.Search.Grouping
         {
             get
             {
-                return GetCollectedGroupHeads().Count;
+                return CollectedGroupHeads.Count;
             }
         }
 
@@ -105,7 +105,7 @@ namespace Lucene.Net.Search.Grouping
         /// Subsequent calls should return the same group heads.
         /// </summary>
         /// <returns>the collected group heads</returns>
-        protected abstract ICollection<GH> GetCollectedGroupHeads();
+        protected abstract ICollection<GH> CollectedGroupHeads { get; }
 
         public override void Collect(int doc)
         {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/04f4013d/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
index 70a2033..f9e7d0b 100644
--- a/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Function/FunctionAllGroupHeadsCollector.cs
@@ -80,9 +80,9 @@ namespace Lucene.Net.Search.Grouping.Function
             this.temporalResult.groupHead = groupHead;
         }
 
-        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        protected override ICollection<GroupHead> CollectedGroupHeads
         {
-            return groups.Values;
+            get { return groups.Values; }
         }
 
         public override Scorer Scorer

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/04f4013d/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
index 175dd0a..a89712d 100644
--- a/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
+++ b/src/Lucene.Net.Grouping/Term/TermAllGroupHeadsCollector.cs
@@ -185,9 +185,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             temporalResult.groupHead = groupHead;
         }
 
-        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        protected override ICollection<GroupHead> CollectedGroupHeads
         {
-            return groups.Values;
+            get { return groups.Values; }
         }
 
         public override AtomicReaderContext NextReader
@@ -295,9 +295,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        protected override ICollection<GroupHead> CollectedGroupHeads
         {
-            return collectedGroups;
+            get { return collectedGroups; }
         }
 
         public override Scorer Scorer
@@ -527,9 +527,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        protected override ICollection<GroupHead> CollectedGroupHeads
         {
-            return collectedGroups;
+            get { return collectedGroups; }
         }
 
         public override Scorer Scorer
@@ -716,9 +716,9 @@ namespace Lucene.Net.Search.Grouping.Terms
             }
         }
 
-        protected override ICollection<GroupHead> GetCollectedGroupHeads()
+        protected override ICollection<GroupHead> CollectedGroupHeads
         {
-            return collectedGroups;
+            get { return collectedGroups; }
         }
 
         public override Scorer Scorer


[45/58] [abbrv] lucenenet git commit: Fixed random bug in SearchGroup - replaced SortedSet with TreeSet

Posted by ni...@apache.org.
Fixed random bug in SearchGroup - replaced SortedSet with TreeSet


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

Branch: refs/heads/grouping
Commit: 7c01e8865290dae7f3367c6e9fb7c00d8d76f8a6
Parents: 4b914b7
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 01:39:42 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:57 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Grouping/SearchGroup.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7c01e886/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index 126e974..a225f3c 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -206,13 +206,13 @@ namespace Lucene.Net.Search.Grouping
         {
 
             private readonly GroupComparator<T> groupComp;
-            private readonly ISet<MergedGroup<T>> queue;
+            private readonly TreeSet<MergedGroup<T>> queue;
             private readonly IDictionary<T, MergedGroup<T>> groupsSeen;
 
             public GroupMerger(Sort groupSort)
             {
                 groupComp = new GroupComparator<T>(groupSort);
-                queue = new SortedSet<MergedGroup<T>>(groupComp);
+                queue = new TreeSet<MergedGroup<T>>(groupComp);
                 groupsSeen = new HashMap<T, MergedGroup<T>>();
             }
 


[16/58] [abbrv] lucenenet git commit: Revert "HACK: Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context."

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs b/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
index 264e95c..eb92962 100644
--- a/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
+++ b/src/Lucene.Net.Tests/core/Support/TestLurchTable.cs
@@ -529,118 +529,6 @@ namespace Lucene.Net.Support
                 return KeyComparer.GetHashCode(obj.Key) ^ ValueComparer.GetHashCode(obj.Value);
             }
         }
-
-
-        #region TestGenericCollection<TList, TItem>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestAddRemove()
-        {
-            base.TestAddRemove();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestAddReverseRemove()
-        {
-            base.TestAddReverseRemove();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestClear()
-        {
-            base.TestClear();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestContains()
-        {
-            base.TestContains();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestCopyTo()
-        {
-            base.TestCopyTo();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestIsReadOnly()
-        {
-            base.TestIsReadOnly();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestGetEnumerator()
-        {
-            base.TestGetEnumerator();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGenericCollection_TestGetEnumerator2()
-        {
-            base.TestGetEnumerator2();
-        }
-
-        #endregion
-
-        #region TestCollection<TList, TFactory, TItem>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestAddRemove()
-        {
-            base.TestAddRemove();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestAddReverseRemove()
-        {
-            base.TestAddReverseRemove();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestClear()
-        {
-            base.TestClear();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestContains()
-        {
-            base.TestContains();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestCopyTo()
-        {
-            base.TestCopyTo();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestIsReadOnly()
-        {
-            base.TestIsReadOnly();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestGetEnumerator()
-        {
-            base.TestGetEnumerator();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollection_TestGetEnumerator2()
-        {
-            base.TestGetEnumerator2();
-        }
-
-        #endregion
-
     }
 
     [TestFixture]
@@ -665,32 +553,6 @@ namespace Lucene.Net.Support
             }
             return results.ToArray();
         }
-
-
-        #region TestDictionary<TDictionary, TFactory, TKey, TValue>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test, LuceneNetSpecific]
-        public void TestDictionary_TestAddRemoveByKey()
-        {
-            base.TestAddRemoveByKey();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestDictionary_TestKeys()
-        {
-            base.TestKeys();
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestDictionary_TestValues()
-        {
-            base.TestValues();
-        }
-
-        #endregion
     }
 
 
@@ -717,7 +579,7 @@ namespace Lucene.Net.Support
             return list;
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestAddRemove()
         {
             TList list = new TList();
@@ -738,7 +600,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestAddReverseRemove()
         {
             TList list = new TList();
@@ -759,7 +621,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestClear()
         {
             TList list = new TList();
@@ -774,7 +636,7 @@ namespace Lucene.Net.Support
             Assert.AreEqual(0, list.Count);
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestContains()
         {
             TList list = new TList();
@@ -788,7 +650,7 @@ namespace Lucene.Net.Support
                 Assert.IsTrue(list.Contains(item));
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestCopyTo()
         {
             TList list = new TList();
@@ -808,13 +670,13 @@ namespace Lucene.Net.Support
             Assert.AreEqual(0, items.Count);
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestIsReadOnly()
         {
             Assert.IsFalse(new TList().IsReadOnly);
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestGetEnumerator()
         {
             TList list = new TList();
@@ -830,7 +692,7 @@ namespace Lucene.Net.Support
             Assert.AreEqual(0, items.Count);
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestGetEnumerator2()
         {
             TList list = new TList();
@@ -896,7 +758,7 @@ namespace Lucene.Net.Support
         where TDictionary : IDictionary<TKey, TValue>, IDisposable
         where TFactory : IFactory<TDictionary>, new()
     {
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestAddRemoveByKey()
         {
             KeyValuePair<TKey, TValue>[] sample = GetSample();
@@ -918,7 +780,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestKeys()
         {
             KeyValuePair<TKey, TValue>[] sample = GetSample();
@@ -941,7 +803,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestValues()
         {
             KeyValuePair<TKey, TValue>[] sample = GetSample();
@@ -970,7 +832,7 @@ namespace Lucene.Net.Support
 
         protected readonly TFactory Factory = new TFactory();
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestAddRemove()
         {
             using (TList list = Factory.Create())
@@ -993,7 +855,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestAddReverseRemove()
         {
             using (TList list = Factory.Create())
@@ -1016,7 +878,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestClear()
         {
             using (TList list = Factory.Create())
@@ -1033,7 +895,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestContains()
         {
             using (TList list = Factory.Create())
@@ -1049,7 +911,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestCopyTo()
         {
             using (TList list = Factory.Create())
@@ -1071,14 +933,14 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestIsReadOnly()
         {
             using (TList list = Factory.Create())
                 Assert.IsFalse(list.IsReadOnly);
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestGetEnumerator()
         {
             using (TList list = Factory.Create())
@@ -1096,7 +958,7 @@ namespace Lucene.Net.Support
             }
         }
 
-        // [Test, LuceneNetSpecific] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test, LuceneNetSpecific]
         public virtual void TestGetEnumerator2()
         {
             using (TList list = Factory.Create())

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs b/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
index 51ac7e2..dd31909 100644
--- a/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
+++ b/src/Lucene.Net.Tests/core/Util/BaseSortTestCase.cs
@@ -153,55 +153,55 @@ namespace Lucene.Net.Util
             DoTest(strategy, Random().Next(20000));
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestEmpty()
         {
             SortTest(new Entry[0]);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestOne()
         {
             DoTest(RandomStrategy, 1);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestTwo()
         {
             DoTest(RandomStrategy, 2);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestRandom()
         {
             DoTest(RandomStrategy);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestRandomLowCardinality()
         {
             DoTest(RandomLowCardinalityStrategy, 2);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestAscending()
         {
             DoTest(AscendingStrategy, 2);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestAscendingSequences()
         {
             DoTest(AscendingSequencesStrategy, 2);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestDescending()
         {
             DoTest(DescendingStrategy, 2);
         }
 
-        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
+        [Test]
         public virtual void TestStrictlyDescendingStrategy()
         {
             DoTest(StrictlyDescendingStrategy, 2);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs b/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
index 38d63a1..91c7062 100644
--- a/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/Packed/TestEliasFanoDocIdSet.cs
@@ -1,5 +1,4 @@
 using Lucene.Net.Support;
-using NUnit.Framework;
 using System.Collections;
 using System.Diagnostics;
 
@@ -76,49 +75,5 @@ namespace Lucene.Net.Util.Packed
                 return SlowAdvance(target);
             }
         }
-
-
-        #region BaseDocIdSetTestCase<T>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// Test length=0.
-        /// </summary>
-        [Test]
-        public override void TestNoBit()
-        {
-            base.TestNoBit();
-        }
-
-        /// <summary>
-        /// Test length=1.
-        /// </summary>
-        [Test]
-        public override void Test1Bit()
-        {
-            base.Test1Bit();
-        }
-
-        /// <summary>
-        /// Test length=2.
-        /// </summary>
-        [Test]
-        public override void Test2Bits()
-        {
-            base.Test2Bits();
-        }
-
-        /// <summary>
-        /// Compare the content of the set against a <seealso cref="BitSet"/>.
-        /// </summary>
-        [Test]
-        public override void TestAgainstBitSet()
-        {
-            base.TestAgainstBitSet();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs b/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
index bb779c5..1294bff 100644
--- a/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestDocIdBitSet.cs
@@ -1,5 +1,3 @@
-using Lucene.Net.Attributes;
-using NUnit.Framework;
 using System.Collections;
 
 namespace Lucene.Net.Util
@@ -27,49 +25,5 @@ namespace Lucene.Net.Util
         {
             return new DocIdBitSet((BitArray)bs.Clone());
         }
-
-
-        #region BaseDocIdSetTestCase<T>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// Test length=0.
-        /// </summary>
-        [Test]
-        public override void TestNoBit()
-        {
-            base.TestNoBit();
-        }
-
-        /// <summary>
-        /// Test length=1.
-        /// </summary>
-        [Test]
-        public override void Test1Bit()
-        {
-            base.Test1Bit();
-        }
-
-        /// <summary>
-        /// Test length=2.
-        /// </summary>
-        [Test]
-        public override void Test2Bits()
-        {
-            base.Test2Bits();
-        }
-
-        /// <summary>
-        /// Compare the content of the set against a <seealso cref="BitSet"/>.
-        /// </summary>
-        [Test, LongRunningTest, Timeout(150000)]
-        public override void TestAgainstBitSet()
-        {
-            base.TestAgainstBitSet();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs b/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
index 2f822f9..550b3e1 100644
--- a/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestFixedBitSet.cs
@@ -1,5 +1,4 @@
 using System;
-using Lucene.Net.Attributes;
 using Lucene.Net.Randomized.Generators;
 using Lucene.Net.Support;
 using NUnit.Framework;
@@ -511,49 +510,5 @@ namespace Lucene.Net.Util
             Assert.IsTrue(bits.Get(1));
             Assert.IsFalse(newBits.Get(1));
         }
-
-
-        #region BaseDocIdSetTestCase<T>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// Test length=0.
-        /// </summary>
-        [Test]
-        public override void TestNoBit()
-        {
-            base.TestNoBit();
-        }
-
-        /// <summary>
-        /// Test length=1.
-        /// </summary>
-        [Test]
-        public override void Test1Bit()
-        {
-            base.Test1Bit();
-        }
-
-        /// <summary>
-        /// Test length=2.
-        /// </summary>
-        [Test]
-        public override void Test2Bits()
-        {
-            base.Test2Bits();
-        }
-
-        /// <summary>
-        /// Compare the content of the set against a <seealso cref="BitSet"/>.
-        /// </summary>
-        [Test, LongRunningTest, Timeout(150000)]
-        public override void TestAgainstBitSet()
-        {
-            base.TestAgainstBitSet();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs b/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
index 3649531..5c35706 100644
--- a/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestInPlaceMergeSorter.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Util
 {
     /*
@@ -34,67 +32,5 @@ namespace Lucene.Net.Util
         {
             return new ArrayInPlaceMergeSorter<Entry>(arr, ArrayUtil.naturalComparator<Entry>());
         }
-
-
-        #region BaseSortTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestEmpty()
-        {
-            base.TestEmpty();
-        }
-
-        [Test]
-        public override void TestOne()
-        {
-            base.TestOne();
-        }
-
-        [Test]
-        public override void TestTwo()
-        {
-            base.TestTwo();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestRandomLowCardinality()
-        {
-            base.TestRandomLowCardinality();
-        }
-
-        [Test]
-        public override void TestAscending()
-        {
-            base.TestAscending();
-        }
-
-        [Test]
-        public override void TestAscendingSequences()
-        {
-            base.TestAscendingSequences();
-        }
-
-        [Test]
-        public override void TestDescending()
-        {
-            base.TestDescending();
-        }
-
-        [Test]
-        public override void TestStrictlyDescendingStrategy()
-        {
-            base.TestStrictlyDescendingStrategy();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs b/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
index b2c75f8..c71893a 100644
--- a/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestIntroSorter.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Util
 {
     /*
@@ -30,67 +28,5 @@ namespace Lucene.Net.Util
         {
             return new ArrayIntroSorter<Entry>(arr, ArrayUtil.naturalComparator<Entry>());
         }
-
-
-        #region BaseSortTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestEmpty()
-        {
-            base.TestEmpty();
-        }
-
-        [Test]
-        public override void TestOne()
-        {
-            base.TestOne();
-        }
-
-        [Test]
-        public override void TestTwo()
-        {
-            base.TestTwo();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestRandomLowCardinality()
-        {
-            base.TestRandomLowCardinality();
-        }
-
-        [Test]
-        public override void TestAscending()
-        {
-            base.TestAscending();
-        }
-
-        [Test]
-        public override void TestAscendingSequences()
-        {
-            base.TestAscendingSequences();
-        }
-
-        [Test]
-        public override void TestDescending()
-        {
-            base.TestDescending();
-        }
-
-        [Test]
-        public override void TestStrictlyDescendingStrategy()
-        {
-            base.TestStrictlyDescendingStrategy();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs b/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
index 8144d1c..c72aa45 100644
--- a/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestOpenBitSet.cs
@@ -514,49 +514,5 @@ namespace Lucene.Net.Util
             bits.FastSet(bit - 1);
             Assert.IsTrue(bits.FastGet(bit - 1));
         }
-
-
-        #region BaseDocIdSetTestCase<T>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// Test length=0.
-        /// </summary>
-        [Test]
-        public override void TestNoBit()
-        {
-            base.TestNoBit();
-        }
-
-        /// <summary>
-        /// Test length=1.
-        /// </summary>
-        [Test]
-        public override void Test1Bit()
-        {
-            base.Test1Bit();
-        }
-
-        /// <summary>
-        /// Test length=2.
-        /// </summary>
-        [Test]
-        public override void Test2Bits()
-        {
-            base.Test2Bits();
-        }
-
-        /// <summary>
-        /// Compare the content of the set against a <seealso cref="BitSet"/>.
-        /// </summary>
-        [Test, LongRunningTest, Timeout(150000)]
-        public override void TestAgainstBitSet()
-        {
-            base.TestAgainstBitSet();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs b/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
index b310b7b..3c92150 100644
--- a/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestPForDeltaDocIdSet.cs
@@ -38,49 +38,5 @@ namespace Lucene.Net.Util
             base.AssertEquals(numBits, ds1, ds2);
             Assert.AreEqual(ds1.Cardinality(), ds2.Cardinality());
         }
-
-
-        #region BaseDocIdSetTestCase<T>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// Test length=0.
-        /// </summary>
-        [Test]
-        public override void TestNoBit()
-        {
-            base.TestNoBit();
-        }
-
-        /// <summary>
-        /// Test length=1.
-        /// </summary>
-        [Test]
-        public override void Test1Bit()
-        {
-            base.Test1Bit();
-        }
-
-        /// <summary>
-        /// Test length=2.
-        /// </summary>
-        [Test]
-        public override void Test2Bits()
-        {
-            base.Test2Bits();
-        }
-
-        /// <summary>
-        /// Compare the content of the set against a <seealso cref="BitSet"/>.
-        /// </summary>
-        [Test]
-        public override void TestAgainstBitSet()
-        {
-            base.TestAgainstBitSet();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs b/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
index 8f13308..c12b850 100644
--- a/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestTimSorter.cs
@@ -1,5 +1,3 @@
-using NUnit.Framework;
-
 namespace Lucene.Net.Util
 {
     /*
@@ -30,67 +28,5 @@ namespace Lucene.Net.Util
         {
             return new ArrayTimSorter<Entry>(arr, ArrayUtil.naturalComparator<Entry>(), TestUtil.NextInt(Random(), 0, arr.Length));
         }
-
-
-        #region BaseSortTestCase
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        [Test]
-        public override void TestEmpty()
-        {
-            base.TestEmpty();
-        }
-
-        [Test]
-        public override void TestOne()
-        {
-            base.TestOne();
-        }
-
-        [Test]
-        public override void TestTwo()
-        {
-            base.TestTwo();
-        }
-
-        [Test]
-        public override void TestRandom()
-        {
-            base.TestRandom();
-        }
-
-        [Test]
-        public override void TestRandomLowCardinality()
-        {
-            base.TestRandomLowCardinality();
-        }
-
-        [Test]
-        public override void TestAscending()
-        {
-            base.TestAscending();
-        }
-
-        [Test]
-        public override void TestAscendingSequences()
-        {
-            base.TestAscendingSequences();
-        }
-
-        [Test]
-        public override void TestDescending()
-        {
-            base.TestDescending();
-        }
-
-        [Test]
-        public override void TestStrictlyDescendingStrategy()
-        {
-            base.TestStrictlyDescendingStrategy();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/d67ed2b2/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs b/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
index b0d3ea0..73d338d 100644
--- a/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestWAH8DocIdSet.cs
@@ -106,49 +106,5 @@ namespace Lucene.Net.Util
             }
             AssertEquals(numBits, expected, union);
         }
-
-
-        #region BaseDocIdSetTestCase<T>
-        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
-        // context in Visual Studio. This fixes that with the minimum amount of code necessary
-        // to run them in the correct context without duplicating all of the tests.
-
-        /// <summary>
-        /// Test length=0.
-        /// </summary>
-        [Test]
-        public override void TestNoBit()
-        {
-            base.TestNoBit();
-        }
-
-        /// <summary>
-        /// Test length=1.
-        /// </summary>
-        [Test]
-        public override void Test1Bit()
-        {
-            base.Test1Bit();
-        }
-
-        /// <summary>
-        /// Test length=2.
-        /// </summary>
-        [Test]
-        public override void Test2Bits()
-        {
-            base.Test2Bits();
-        }
-
-        /// <summary>
-        /// Compare the content of the set against a <seealso cref="BitSet"/>.
-        /// </summary>
-        [Test]
-        public override void TestAgainstBitSet()
-        {
-            base.TestAgainstBitSet();
-        }
-
-        #endregion
     }
 }
\ No newline at end of file


[13/58] [abbrv] lucenenet git commit: Core.Support.TreeSet: Implemented ISet, since it was missing from the original C5 implementation

Posted by ni...@apache.org.
Core.Support.TreeSet: Implemented ISet<T>, since it was missing from the original C5 implementation


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

Branch: refs/heads/grouping
Commit: a0f684de9dbf46a7f9a0119609318584b6c16011
Parents: 5f19852
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 20:28:27 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Mon Nov 7 18:44:12 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Support/TreeSet.cs | 185 +++++++++++++++++++++++++++-
 1 file changed, 184 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a0f684de/src/Lucene.Net.Core/Support/TreeSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Support/TreeSet.cs b/src/Lucene.Net.Core/Support/TreeSet.cs
index 4ce8831..b77d711 100644
--- a/src/Lucene.Net.Core/Support/TreeSet.cs
+++ b/src/Lucene.Net.Core/Support/TreeSet.cs
@@ -21,6 +21,7 @@
 
 using Lucene.Net.Support.C5;
 using System;
+using System.Linq;
 using SCG = System.Collections.Generic;
 
 namespace Lucene.Net.Support
@@ -40,7 +41,7 @@ namespace Lucene.Net.Support
     /// leak possible with other usage modes.</i>
     /// </summary>
     [Serializable]
-    public class TreeSet<T> : SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>
+    public class TreeSet<T> : SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>, SCG.ISet<T>
     {
         #region Fields
 
@@ -539,6 +540,188 @@ namespace Lucene.Net.Support
 
         #endregion
 
+        #region ISet<T> Members
+
+        /// <summary>
+        /// Modifies the current <see cref="TreeSet{T}"/> object to contain all elements that are present in itself, the specified collection, or both.
+        /// </summary>
+        /// <param name="other"></param>
+        public void UnionWith(SCG.IEnumerable<T> other)
+        {
+            AddAll(other);
+        }
+
+        /// <summary>
+        /// Not implemented
+        /// </summary>
+        /// <param name="other"></param>
+        public void IntersectWith(SCG.IEnumerable<T> other)
+        {
+            throw new NotImplementedException("Implement as required");
+        }
+
+        /// <summary>
+        /// Not implemented
+        /// </summary>
+        /// <param name="other"></param>
+        public void ExceptWith(SCG.IEnumerable<T> other)
+        {
+            throw new NotImplementedException("Implement as required");
+        }
+
+        /// <summary>
+        /// Not implemented
+        /// </summary>
+        /// <param name="other"></param>
+        public void SymmetricExceptWith(SCG.IEnumerable<T> other)
+        {
+            throw new NotImplementedException("Implement as required");
+        }
+
+        /// <summary>
+        /// Determines whether a <see cref="TreeSet{T}"/> object is a subset of the specified collection.
+        /// </summary>
+        /// <param name="other">The collection to compare to the current <see cref="TreeSet{T}"/> object.</param>
+        /// <returns><c>true</c> if the <see cref="TreeSet{T}"/> object is a subset of other; otherwise, <c>false</c>.</returns>
+        public bool IsSubsetOf(SCG.IEnumerable<T> other)
+        {
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            if (this.Count == 0)
+            {
+                return true;
+            }
+            // we just need to return true if the other set
+            // contains all of the elements of the this set,
+            // but we need to use the comparison rules of the current set.
+            int foundCount, unfoundCount;
+            this.GetFoundAndUnfoundCounts(other, out foundCount, out unfoundCount);
+            return foundCount == this.Count;
+        }
+
+        /// <summary>
+        /// Determines whether a <see cref="TreeSet{T}"/> object is a superset of the specified collection.
+        /// </summary>
+        /// <param name="other">The collection to compare to the current <see cref="TreeSet{T}"/> object.</param>
+        /// <returns><c>true</c> if the <see cref="TreeSet{T}"/> object is a superset of other; otherwise, <c>false</c>.</returns>
+        public bool IsSupersetOf(SCG.IEnumerable<T> other)
+        {
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            ICollection<T> is2 = other as ICollection<T>;
+            if (is2 != null && is2.Count == 0)
+            {
+                return true;
+            }
+            return this.ContainsAll(other);
+        }
+
+        /// <summary>
+        /// Determines whether a <see cref="TreeSet{T}"/> object is a proper superset of the specified collection.
+        /// </summary>
+        /// <param name="other">The collection to compare to the current <see cref="TreeSet{T}"/> object.</param>
+        /// <returns><c>true</c> if the <see cref="TreeSet{T}"/> object is a proper superset of other; otherwise, <c>false</c>.</returns>
+        public bool IsProperSupersetOf(SCG.IEnumerable<T> other)
+        {
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            if (this.Count == 0)
+            {
+                return false;
+            }
+            ICollection<T> is2 = other as ICollection<T>;
+            if (is2 != null && is2.Count == 0)
+            {
+                return true;
+            }
+            int foundCount, unfoundCount;
+            this.GetFoundAndUnfoundCounts(other, out foundCount, out unfoundCount);
+            return foundCount < this.Count && unfoundCount == 0;
+        }
+
+        /// <summary>
+        /// Determines whether a <see cref="TreeSet{T}"/> object is a proper subset of the specified collection.
+        /// </summary>
+        /// <param name="other">The collection to compare to the current <see cref="TreeSet{T}"/> object.</param>
+        /// <returns><c>true</c> if the <see cref="TreeSet{T}"/> object is a proper subset of other; otherwise, <c>false</c>.</returns>
+        public bool IsProperSubsetOf(SCG.IEnumerable<T> other)
+        {
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            ICollection<T> is2 = other as ICollection<T>;
+            if (is2 != null && this.Count == 0)
+            {
+                return (is2.Count > 0);
+            }
+            // we just need to return true if the other set
+            // contains all of the elements of the this set plus at least one more,
+            // but we need to use the comparison rules of the current set.
+            int foundCount, unfoundCount;
+            this.GetFoundAndUnfoundCounts(other, out foundCount, out unfoundCount);
+            return foundCount == this.Count && unfoundCount > 0;
+        }
+
+        /// <summary>
+        /// Determines whether the current <see cref="TreeSet{T}"/> object and a specified collection share common elements.
+        /// </summary>
+        /// <param name="other">The collection to compare to the current <see cref="TreeSet{T}"/> object.</param>
+        /// <returns><c>true</c> if the <see cref="TreeSet{T}"/> object and other share at least one common element; otherwise, <c>false</c>.</returns>
+        public bool Overlaps(SCG.IEnumerable<T> other)
+        {
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            if (this.Count != 0)
+            {
+                foreach (var local in other)
+                {
+                    if (this.Contains(local))
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Determines whether the current <see cref="TreeSet{T}"/> and the specified collection contain the same elements.
+        /// </summary>
+        /// <param name="other">The collection to compare to the current <see cref="TreeSet{T}"/>.</param>
+        /// <returns><c>true</c> if the current <see cref="TreeSet{T}"/> is equal to other; otherwise, <c>false</c>.</returns>
+        public bool SetEquals(SCG.IEnumerable<T> other)
+        {
+            return this.Count.Equals(other.Count()) && this.ContainsAll(other);
+        }
+
+        private void GetFoundAndUnfoundCounts(SCG.IEnumerable<T> other, out int foundCount, out int unfoundCount)
+        {
+            foundCount = 0;
+            unfoundCount = 0;
+            foreach (var item in other)
+            {
+                if (this.Contains(item))
+                {
+                    foundCount++;
+                }
+                else
+                {
+                    unfoundCount++;
+                }
+            }
+        }
+
+        #endregion
+
         #region IEnumerable<T> Members
 
         /// <summary>


[05/58] [abbrv] lucenenet git commit: Added TreeSet and TreeDictionary from C5 to the Support namespace

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/Events.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/Events.cs b/src/Lucene.Net.Tests/core/Support/C5/Events.cs
new file mode 100644
index 0000000..f0f5082
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/Events.cs
@@ -0,0 +1,893 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using Lucene.Net.Support.C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.Templates.Events
+{
+    public abstract class CollectionValueTester<TCollection, TItem> : GenericCollectionTester<TCollection, EventTypeEnum>
+      where TCollection : ICollectionValue<TItem>
+    {
+        protected TCollection collection;
+        protected CollectionEventList<TItem> seen;
+        protected EventTypeEnum listenTo;
+        protected void listen() { seen.Listen(collection, listenTo); }
+
+        public override void SetUp(TCollection list, EventTypeEnum testSpec, MemoryType memoryType)
+        {
+            this.collection = list;
+            listenTo = testSpec;
+            seen = new CollectionEventList<TItem>(EqualityComparer<TItem>.Default, memoryType);
+        }
+
+        public SCG.IEnumerable<EventTypeEnum> SpecsBasic
+        {
+            get
+            {
+                CircularQueue<EventTypeEnum> specs = new CircularQueue<EventTypeEnum>();
+                //foreach (EventTypeEnum listenTo in Enum.GetValues(typeof(EventTypeEnum)))
+                //  if ((listenTo & ~EventTypeEnum.Basic) == 0)
+                //    specs.Enqueue(listenTo);
+                //specs.Enqueue(EventTypeEnum.Added | EventTypeEnum.Removed);
+                for (int spec = 0; spec <= (int)EventTypeEnum.Basic; spec++)
+                    specs.Enqueue((EventTypeEnum)spec);
+                return specs;
+            }
+        }
+        public SCG.IEnumerable<EventTypeEnum> SpecsAll
+        {
+            get
+            {
+                CircularQueue<EventTypeEnum> specs = new CircularQueue<EventTypeEnum>();
+                //foreach (EventTypeEnum listenTo in Enum.GetValues(typeof(EventTypeEnum)))
+                //  specs.Enqueue(listenTo);
+                //specs.Enqueue(EventTypeEnum.Added | EventTypeEnum.Removed);
+
+                for (int spec = 0; spec <= (int)EventTypeEnum.All; spec++)
+                    specs.Enqueue((EventTypeEnum)spec);
+                return specs;
+            }
+        }
+    }
+    public abstract class CollectionValueTester<U> : CollectionValueTester<U, int> where U : ICollectionValue<int>
+    {
+    }
+
+    public class ExtensibleTester<U> : CollectionValueTester<U> where U : IExtensible<int>
+    {
+        public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+        {
+            return SpecsBasic;
+        }
+        public virtual void Listenable()
+        {
+            Assert.AreEqual(EventTypeEnum.Basic, collection.ListenableEvents);
+            Assert.AreEqual(EventTypeEnum.None, collection.ActiveEvents);
+            listen();
+            Assert.AreEqual(listenTo, collection.ActiveEvents);
+        }
+
+        public void Add()
+        {
+            listen();
+            seen.Check(new CollectionEvent<int>[0]);
+            collection.Add(23);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+        public void AddAll()
+        {
+            for (int i = 0; i < 10; i++)
+            {
+                collection.Add(10 * i + 5);
+            }
+            listen();
+            collection.AddAll(new int[] { 45, 200, 56, 67 });
+            seen.Check(collection.AllowsDuplicates ?
+              collection.DuplicatesByCounting ?
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(200, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(55, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(65, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+              :
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(200, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+                :
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(200, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.AddAll(new int[] { });
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+    }
+
+    public class CollectionTester<U> : ExtensibleTester<U> where U : ICollection<int>
+    {
+        public void Update()
+        {
+            collection.Add(4); collection.Add(54); collection.Add(56); collection.Add(8);
+            listen();
+            collection.Update(53);
+            seen.Check(
+              collection.AllowsDuplicates ?
+              collection.DuplicatesByCounting ?
+              new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(54, 2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          }
+              : new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(54, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          }
+              : new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(54, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+            collection.Update(67);
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void FindOrAdd()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            int val = 53;
+            collection.FindOrAdd(ref val);
+            seen.Check(new CollectionEvent<int>[] { });
+            val = 67;
+            collection.FindOrAdd(ref val);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+        }
+
+        public void UpdateOrAdd()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            int val = 53;
+            collection.UpdateOrAdd(val);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            val = 67;
+            collection.UpdateOrAdd(val);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.UpdateOrAdd(51, out val);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(51, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            val = 67;
+            collection.UpdateOrAdd(81, out val);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(81, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+        }
+
+        public void RemoveItem()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.Remove(53);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Remove(11);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+        public void RemoveAll()
+        {
+            for (int i = 0; i < 10; i++)
+            {
+                collection.Add(10 * i + 5);
+            }
+            listen();
+            collection.RemoveAll(new int[] { 32, 187, 45 });
+            //TODO: the order depends on internals of the HashSet
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(35, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.RemoveAll(new int[] { 200, 300 });
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void RetainAll()
+        {
+            for (int i = 0; i < 10; i++)
+            {
+                collection.Add(10 * i + 5);
+            }
+            listen();
+            collection.RetainAll(new int[] { 32, 187, 45, 62, 75, 82, 95, 2 });
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(55, 1), collection),
+          //new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(75, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.RetainAll(new int[] { 32, 187, 45, 62, 75, 82, 95, 2 });
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void RemoveAllCopies()
+        {
+            for (int i = 0; i < 10; i++)
+            {
+                collection.Add(3 * i + 5);
+            }
+            listen();
+            collection.RemoveAllCopies(14);
+            seen.Check(
+              collection.AllowsDuplicates ?
+                collection.DuplicatesByCounting ?
+                  new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 3), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+                :
+                new CollectionEvent<int>[] {
+            new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), collection),
+            new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(14, 1), collection),
+            new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(17, 1), collection),
+            new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+              :
+              new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.RemoveAllCopies(14);
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public virtual void Clear()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection.Clear();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedEventArgs(true, collection.AllowsDuplicates ? 3 : 2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.Clear();
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+    }
+
+    public class IndexedTester<U> : CollectionTester<U> where U : IIndexed<int>
+    {
+        public void RemoveAt()
+        {
+            collection.Add(4); collection.Add(16); collection.Add(28);
+            listen();
+            collection.RemoveAt(1);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(16,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(16, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+        public void RemoveInterval()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.RemoveInterval(1, 2);
+            seen.Check(new CollectionEvent<int>[] {
+        collection is IList<int> ?
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,2,1), collection):
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedEventArgs(false,2), collection),
+         new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.RemoveInterval(1, 0);
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+    }
+
+    public class SortedIndexedTester<U> : IndexedTester<U> where U : IIndexedSorted<int>
+    {
+        public void DeleteMinMax()
+        {
+            collection.Add(34);
+            collection.Add(56);
+            collection.Add(34);
+            collection.Add(12);
+            listen();
+            collection.DeleteMax();
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.DeleteMin();
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(12, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+        }
+
+        public void AddSorted()
+        {
+            listen();
+            collection.AddSorted(collection.AllowsDuplicates ? new int[] { 31, 62, 63, 93 } : new int[] { 31, 62, 93 });
+            seen.Check(collection.AllowsDuplicates ?
+              collection.DuplicatesByCounting ?
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(31, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(93, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+              :
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(31, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(63, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(93, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+                :
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(31, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(93, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.AddSorted(new int[] { });
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void RemoveRange()
+        {
+            for (int i = 0; i < 20; i++)
+                collection.Add(i * 10 + 5);
+            listen();
+            collection.RemoveRangeFrom(173);
+            //TODO: fix order to remove in:
+            seen.Check(
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(195, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(185, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(175, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.RemoveRangeFromTo(83, 113);
+            seen.Check(
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(105, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(95, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(85, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.RemoveRangeTo(33);
+            seen.Check(
+                new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(5, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.RemoveRangeFrom(173);
+            seen.Check(new CollectionEvent<int>[] { });
+            collection.RemoveRangeFromTo(83, 113);
+            seen.Check(new CollectionEvent<int>[] { });
+            collection.RemoveRangeTo(33);
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+    }
+
+    public class ListTester<U> : IndexedTester<U> where U : IList<int>
+    {
+        public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+        {
+            return SpecsAll;
+        }
+
+        public override void Listenable()
+        {
+            Assert.AreEqual(EventTypeEnum.All, collection.ListenableEvents);
+            Assert.AreEqual(EventTypeEnum.None, collection.ActiveEvents);
+            listen();
+            Assert.AreEqual(listenTo, collection.ActiveEvents);
+        }
+        public void SetThis()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection[1] = 45;
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+        }
+
+        public void Insert()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection.Insert(1, 45);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+        }
+
+        public void InsertAll()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection.InsertAll(1, new int[] { 666, 777, 888 });
+            //seen.Print(Console.Error);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(666,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(666, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(777,2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(777, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(888,3), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(888, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+            collection.InsertAll(1, new int[] { });
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void InsertFirstLast()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.InsertFirst(45);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+            collection.InsertLast(88);
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(88,4), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(88, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+        }
+
+        public void Remove()
+        {
+            collection.FIFO = false;
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.Remove();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.FIFO = true;
+            collection.Remove();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+        public void RemoveFirst()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.RemoveFirst();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(4,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+        public void RemoveLast()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.RemoveLast();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(18,2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+        public void Reverse()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection.Reverse();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.View(1, 0).Reverse();
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+
+        public void Sort()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection.Sort();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.View(1, 0).Sort();
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void Shuffle()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(8);
+            listen();
+            collection.Shuffle();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.View(1, 0).Shuffle();
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public override void Clear()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.View(1, 1).Clear();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,1,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.Clear();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,2,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.Clear();
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        public void ListDispose()
+        {
+            collection.Add(4); collection.Add(56); collection.Add(18);
+            listen();
+            collection.View(1, 1).Dispose();
+            seen.Check(new CollectionEvent<int>[] { });
+            collection.Dispose();
+            seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,3,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+            collection.Dispose();
+            seen.Check(new CollectionEvent<int>[] { });
+        }
+
+        /* 
+ 
+         * /
+            //[TearDown]
+            //public void Dispose() { list = null; seen = null; }
+            /*
+            [Test]
+            [ExpectedException(typeof(UnlistenableEventException))]
+            public void ViewChanged()
+            {
+              IList<int> w = collection.View(0, 0);
+              w.CollectionChanged += new CollectionChangedHandler<int>(w_CollectionChanged);
+            }
+
+            [Test]
+            [ExpectedException(typeof(UnlistenableEventException))]
+            public void ViewCleared()
+            {
+              IList<int> w = collection.View(0, 0);
+              w.CollectionCleared += new CollectionClearedHandler<int>(w_CollectionCleared);
+            }
+
+            [Test]
+            [ExpectedException(typeof(UnlistenableEventException))]
+            public void ViewAdded()
+            {
+              IList<int> w = collection.View(0, 0);
+              w.ItemsAdded += new ItemsAddedHandler<int>(w_ItemAdded);
+            }
+
+            [Test]
+            [ExpectedException(typeof(UnlistenableEventException))]
+            public void ViewInserted()
+            {
+              IList<int> w = collection.View(0, 0);
+              w.ItemInserted += new ItemInsertedHandler<int>(w_ItemInserted);
+            }
+
+            [Test]
+            [ExpectedException(typeof(UnlistenableEventException))]
+            public void ViewRemoved()
+            {
+              IList<int> w = collection.View(0, 0);
+              w.ItemsRemoved += new ItemsRemovedHandler<int>(w_ItemRemoved);
+            }
+
+            [Test]
+            [ExpectedException(typeof(UnlistenableEventException))]
+            public void ViewRemovedAt()
+            {
+              IList<int> w = collection.View(0, 0);
+              w.ItemRemovedAt += new ItemRemovedAtHandler<int>(w_ItemRemovedAt);
+            }
+
+            void w_CollectionChanged(object sender)
+            {
+              throw new NotImplementedException();
+            }
+
+            void w_CollectionCleared(object sender, ClearedEventArgs eventArgs)
+            {
+              throw new NotImplementedException();
+            }
+
+            void w_ItemAdded(object sender, ItemCountEventArgs<int> eventArgs)
+            {
+              throw new NotImplementedException();
+            }
+
+            void w_ItemInserted(object sender, ItemAtEventArgs<int> eventArgs)
+            {
+              throw new NotImplementedException();
+            }
+
+            void w_ItemRemoved(object sender, ItemCountEventArgs<int> eventArgs)
+            {
+              throw new NotImplementedException();
+            }
+
+            void w_ItemRemovedAt(object sender, ItemAtEventArgs<int> eventArgs)
+            {
+              throw new NotImplementedException();
+            }*/
+    }
+
+    public class StackTester<U> : CollectionValueTester<U> where U : IStack<int>
+    {
+        public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+        {
+            return SpecsBasic;
+        }
+
+        public void PushPop()
+        {
+            listen();
+            seen.Check(new CollectionEvent<int>[0]);
+            collection.Push(23);
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(23,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Push(-12);
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(-12,1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(-12, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Pop();
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(-12,1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(-12, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Pop();
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(23,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(23, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+    }
+
+    public class QueueTester<U> : CollectionValueTester<U> where U : IQueue<int>
+    {
+        public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+        {
+            return SpecsBasic;
+        }
+
+        public void EnqueueDequeue()
+        {
+            listen();
+            collection.Enqueue(67);
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(67,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Enqueue(2);
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(2,1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Dequeue();
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(67,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(67, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Dequeue();
+            seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(2,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(2, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+    }
+
+    public class PriorityQueueTester<U> : ExtensibleTester<U> where U : IPriorityQueue<int>
+    {
+        public override System.Collections.Generic.IEnumerable<EventTypeEnum> GetSpecs()
+        {
+            return SpecsBasic;
+        }
+
+        public void Direct()
+        {
+            listen();
+            collection.Add(34);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.Add(56);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.AddAll(new int[] { });
+            seen.Check(new CollectionEvent<int>[] {
+      });
+            collection.Add(34);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.Add(12);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(12, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.DeleteMax();
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.DeleteMin();
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(12, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.AddAll(new int[] { 4, 5, 6, 2 });
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(4, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(5, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(6, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+      });
+        }
+
+        public void WithHandles()
+        {
+            listen();
+            IPriorityQueueHandle<int> handle = null, handle2;
+            collection.Add(34);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.Add(56);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.Add(ref handle, 34);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.Add(12);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(12, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.DeleteMax(out handle2);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+            collection.DeleteMin(out handle2);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(12, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+
+            collection.Replace(handle, 117);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(34, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(117, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+
+            collection.Delete(handle);
+            seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(117, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection),
+      });
+        }
+    }
+
+    public class DictionaryTester<U> : CollectionValueTester<U, KeyValuePair<int, int>> where U : IDictionary<int, int>
+    {
+        public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+        {
+            return SpecsBasic;
+        }
+
+        public virtual void Listenable()
+        {
+            Assert.AreEqual(EventTypeEnum.Basic, collection.ListenableEvents);
+            Assert.AreEqual(EventTypeEnum.None, collection.ActiveEvents);
+            listen();
+            Assert.AreEqual(listenTo, collection.ActiveEvents);
+        }
+
+        public void AddAndREmove()
+        {
+            listen();
+            seen.Check(new CollectionEvent<KeyValuePair<int, int>>[0]);
+            collection.Add(23, 45);
+            seen.Check(new CollectionEvent<KeyValuePair<int, int>>[] {
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Added, new ItemCountEventArgs<KeyValuePair<int,int>>(new KeyValuePair<int,int>(23,45), 1), collection),
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Changed, new EventArgs(), collection)});
+            collection.Remove(25);
+            seen.Check(new CollectionEvent<KeyValuePair<int, int>>[] {
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Removed, new ItemCountEventArgs<KeyValuePair<int,int>>(new KeyValuePair<int,int>(23,45), 1), collection),
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Changed, new EventArgs(), collection)});
+        }
+
+
+
+    }
+
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/GenericCollectionTester.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/GenericCollectionTester.cs b/src/Lucene.Net.Tests/core/Support/C5/GenericCollectionTester.cs
new file mode 100644
index 0000000..12b4360
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/GenericCollectionTester.cs
@@ -0,0 +1,87 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Reflection;
+using Lucene.Net.Support.C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.Templates
+{
+    public abstract class GenericCollectionTester<U, W>
+    {
+        protected CircularQueue<MethodInfo> testMethods;
+        public GenericCollectionTester()
+        {
+            testMethods = new CircularQueue<MethodInfo>();
+            foreach (MethodInfo minfo in this.GetType().GetMethods())
+            {
+                if (minfo.GetParameters().Length == 0 &&
+                     minfo.GetCustomAttributes(typeof(TestAttribute), false).Length > 0)
+                    testMethods.Enqueue(minfo);
+            }
+        }
+
+        public virtual void Test(Func<U> factory, MemoryType memoryType = MemoryType.Normal)
+        {
+            foreach (MethodInfo minfo in testMethods)
+            {
+                foreach (W testSpec in GetSpecs())
+                {
+                    SetUp(factory(), testSpec, memoryType);
+                    //Console.WriteLine("Testing {0}, with method {1} and testSpec {{{2}}}", typeof(U), minfo.Name, testSpec);
+                    try
+                    {
+                        minfo.Invoke(this, null);
+                    }
+                    catch (TargetInvocationException)
+                    {
+                        //if (e.InnerException is ExpectedExceptionAttribute)
+                        //{
+                        //}
+                        //else
+                        throw;
+                    }
+                    //tearDown
+                }
+            }
+        }
+
+        public abstract void SetUp(U collection, W testSpec, MemoryType memoryType);
+        public abstract SCG.IEnumerable<W> GetSpecs();
+    }
+
+    public abstract class GenericCollectionTester<U> : GenericCollectionTester<U, int>
+    {
+        public override System.Collections.Generic.IEnumerable<int> GetSpecs()
+        {
+            return new int[] { 0 };
+        }
+
+        public override void SetUp(U collection, int testSpec, MemoryType memoryType)
+        {
+            SetUp(collection, memoryType);
+        }
+
+        public abstract void SetUp(object collection, MemoryType memoryType);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/HashBag.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/HashBag.cs b/src/Lucene.Net.Tests/core/Support/C5/HashBag.cs
new file mode 100644
index 0000000..dbfec88
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/HashBag.cs
@@ -0,0 +1,658 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Lucene.Net.Support.C5
+{
+    /// <summary>
+    /// A bag collection based on a hash table of (item,count) pairs. 
+    /// </summary>
+    [Serializable]
+    public class HashBag<T> : CollectionBase<T>, ICollection<T>
+    {
+        #region Fields
+        HashSet<KeyValuePair<T, int>> dict;
+        #endregion
+
+        #region Events
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+        #endregion
+
+        #region Constructors
+        /// <summary>
+        /// Create a hash bag with the default item equalityComparer.
+        /// </summary>
+		public HashBag(MemoryType memoryType = MemoryType.Normal) : this(EqualityComparer<T>.Default, memoryType) { }
+
+        /// <summary>
+        /// Create a hash bag with an external item equalityComparer.
+        /// </summary>
+        /// <param name="itemequalityComparer">The external item equalityComparer.</param>
+		/// <param name = "memoryType"></param>
+		public HashBag(SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(itemequalityComparer, memoryType)
+        {
+            if (memoryType != MemoryType.Normal)
+                throw new Exception("HashBag doesn't still support Safe and Strict memory type.");
+
+            dict = new HashSet<KeyValuePair<T, int>>(new KeyValuePairEqualityComparer<T, int>(itemequalityComparer), memoryType);
+        }
+
+        /// <summary>
+        /// Create a hash bag with external item equalityComparer, prescribed initial table size and default fill threshold (66%)
+        /// </summary>
+        /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>
+        /// <param name="itemequalityComparer">The external item equalitySCG.Comparer</param>
+		/// <param name = "memoryType"></param>
+		public HashBag(int capacity, SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(itemequalityComparer, memoryType)
+        {
+            if (memoryType != MemoryType.Normal)
+                throw new Exception("HashBag doesn't still support Safe and Strict memory type.");
+
+            dict = new HashSet<KeyValuePair<T, int>>(capacity, new KeyValuePairEqualityComparer<T, int>(itemequalityComparer), memoryType);
+        }
+
+
+        /// <summary>
+        /// Create a hash bag with external item equalityComparer, prescribed initial table size and fill threshold.
+        /// </summary>
+        /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>
+        /// <param name="fill">Fill threshold (valid range 10% to 90%)</param>
+        /// <param name="itemequalityComparer">The external item equalitySCG.Comparer</param>
+		/// <param name = "memoryType"></param>
+		public HashBag(int capacity, double fill, SCG.IEqualityComparer<T> itemequalityComparer, MemoryType memoryType = MemoryType.Normal)
+            : base(itemequalityComparer, memoryType)
+        {
+            if (memoryType != MemoryType.Normal)
+                throw new Exception("HashBag doesn't still support Safe and Strict memory type.");
+
+            dict = new HashSet<KeyValuePair<T, int>>(capacity, fill, new KeyValuePairEqualityComparer<T, int>(itemequalityComparer), memoryType);
+        }
+
+        #endregion
+
+        #region IEditableCollection<T> Members
+
+        /// <summary>
+        /// The complexity of the Contains operation
+        /// </summary>
+        /// <value>Always returns Speed.Constant</value>
+        public virtual Speed ContainsSpeed { get { return Speed.Constant; } }
+
+        /// <summary>
+        /// Check if an item is in the bag 
+        /// </summary>
+        /// <param name="item">The item to look for</param>
+        /// <returns>True if bag contains item</returns>
+        public virtual bool Contains(T item)
+        {
+            return dict.Contains(new KeyValuePair<T, int>(item, 0));
+        }
+
+
+        /// <summary>
+        /// Check if an item (collection equal to a given one) is in the bag and
+        /// if so report the actual item object found.
+        /// </summary>
+        /// <param name="item">On entry, the item to look for.
+        /// On exit the item found, if any</param>
+        /// <returns>True if bag contains item</returns>
+        public virtual bool Find(ref T item)
+        {
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+            if (dict.Find(ref p))
+            {
+                item = p.Key;
+                return true;
+            }
+
+            return false;
+        }
+
+
+        /// <summary>
+        /// Check if an item (collection equal to a given one) is in the bag and
+        /// if so replace the item object in the bag with the supplied one.
+        /// </summary>
+        /// <param name="item">The item object to update with</param>
+        /// <returns>True if item was found (and updated)</returns>
+        public virtual bool Update(T item)
+        { T olditem = default(T); return Update(item, out olditem); }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public virtual bool Update(T item, out T olditem)
+        {
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+            updatecheck();
+
+            //Note: we cannot just do dict.Update: we have to lookup the count before we 
+            //know what to update with. There is of course a way around if we use the 
+            //implementation of hashset -which we do not want to do.
+            //The hashbag is moreover mainly a proof of concept
+            if (dict.Find(ref p))
+            {
+                olditem = p.Key;
+                p.Key = item;
+                dict.Update(p);
+                if (ActiveEvents != 0)
+                    raiseForUpdate(item, olditem, p.Value);
+                return true;
+            }
+
+            olditem = default(T);
+            return false;
+        }
+
+
+        /// <summary>
+        /// Check if an item (collection equal to a given one) is in the bag.
+        /// If found, report the actual item object in the bag,
+        /// else add the supplied one.
+        /// </summary>
+        /// <param name="item">On entry, the item to look for or add.
+        /// On exit the actual object found, if any.</param>
+        /// <returns>True if item was found</returns>
+        public virtual bool FindOrAdd(ref T item)
+        {
+            updatecheck();
+            if (Find(ref item))
+                return true;
+
+            Add(item);
+            return false;
+        }
+
+
+        /// <summary>
+        /// Check if an item (collection equal to a supplied one) is in the bag and
+        /// if so replace the item object in the set with the supplied one; else
+        /// add the supplied one.
+        /// </summary>
+        /// <param name="item">The item to look for and update or add</param>
+        /// <returns>True if item was updated</returns>
+        public virtual bool UpdateOrAdd(T item)
+        {
+            updatecheck();
+            if (Update(item))
+                return true;
+
+            Add(item);
+            return false;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="item"></param>
+        /// <param name="olditem"></param>
+        /// <returns></returns>
+        public virtual bool UpdateOrAdd(T item, out T olditem)
+        {
+            updatecheck();
+            if (Update(item, out olditem))
+                return true;
+
+            Add(item);
+            return false;
+        }
+
+        /// <summary>
+        /// Remove one copy of an item from the bag
+        /// </summary>
+        /// <param name="item">The item to remove</param>
+        /// <returns>True if item was (found and) removed </returns>
+        public virtual bool Remove(T item)
+        {
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+            updatecheck();
+            if (dict.Find(ref p))
+            {
+                size--;
+                if (p.Value == 1)
+                    dict.Remove(p);
+                else
+                {
+                    p.Value--;
+                    dict.Update(p);
+                }
+                if (ActiveEvents != 0)
+                    raiseForRemove(p.Key);
+                return true;
+            }
+
+            return false;
+        }
+
+
+        /// <summary>
+        /// Remove one copy of an item from the bag, reporting the actual matching item object.
+        /// </summary>
+        /// <param name="item">The value to remove.</param>
+        /// <param name="removeditem">The removed value.</param>
+        /// <returns>True if item was found.</returns>
+        public virtual bool Remove(T item, out T removeditem)
+        {
+            updatecheck();
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+            if (dict.Find(ref p))
+            {
+                removeditem = p.Key;
+                size--;
+                if (p.Value == 1)
+                    dict.Remove(p);
+                else
+                {
+                    p.Value--;
+                    dict.Update(p);
+                }
+                if (ActiveEvents != 0)
+                    raiseForRemove(removeditem);
+
+                return true;
+            }
+
+            removeditem = default(T);
+            return false;
+        }
+
+        /// <summary>
+        /// Remove all items in a supplied collection from this bag, counting multiplicities.
+        /// </summary>
+        /// <param name="items">The items to remove.</param>
+        public virtual void RemoveAll(SCG.IEnumerable<T> items)
+        {
+#warning Improve if items is a counting bag
+            updatecheck();
+            bool mustRaise = (ActiveEvents & (EventTypeEnum.Changed | EventTypeEnum.Removed)) != 0;
+            RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;
+            foreach (T item in items)
+            {
+                KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+                if (dict.Find(ref p))
+                {
+                    size--;
+                    if (p.Value == 1)
+                        dict.Remove(p);
+                    else
+                    {
+                        p.Value--;
+                        dict.Update(p);
+                    }
+                    if (mustRaise)
+                        raiseHandler.Remove(p.Key);
+                }
+            }
+            if (mustRaise)
+                raiseHandler.Raise();
+        }
+
+        /// <summary>
+        /// Remove all items from the bag, resetting internal table to initial size.
+        /// </summary>
+        public virtual void Clear()
+        {
+            updatecheck();
+            if (size == 0)
+                return;
+            dict.Clear();
+            int oldsize = size;
+            size = 0;
+            if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+                raiseCollectionCleared(true, oldsize);
+            if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                raiseCollectionChanged();
+        }
+
+
+        /// <summary>
+        /// Remove all items *not* in a supplied collection from this bag,
+        /// counting multiplicities.
+        /// </summary>
+        /// <param name="items">The items to retain</param>
+        public virtual void RetainAll(SCG.IEnumerable<T> items)
+        {
+            updatecheck();
+
+            HashBag<T> res = new HashBag<T>(itemequalityComparer);
+
+            foreach (T item in items)
+            {
+                KeyValuePair<T, int> p = new KeyValuePair<T, int>(item);
+                if (dict.Find(ref p))
+                {
+                    KeyValuePair<T, int> q = p;
+                    if (res.dict.Find(ref q))
+                    {
+                        if (q.Value < p.Value)
+                        {
+                            q.Value++;
+                            res.dict.Update(q);
+                            res.size++;
+                        }
+                    }
+                    else
+                    {
+                        q.Value = 1;
+                        res.dict.Add(q);
+                        res.size++;
+                    }
+                }
+            }
+
+            if (size == res.size)
+                return;
+
+            CircularQueue<T> wasRemoved = null;
+            if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+            {
+                wasRemoved = new CircularQueue<T>();
+                foreach (KeyValuePair<T, int> p in dict)
+                {
+                    int removed = p.Value - res.ContainsCount(p.Key);
+                    if (removed > 0)
+#warning We could send bag events here easily using a CircularQueue of (should?)
+                        for (int i = 0; i < removed; i++)
+                            wasRemoved.Enqueue(p.Key);
+                }
+            }
+            dict = res.dict;
+            size = res.size;
+
+            if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+                raiseForRemoveAll(wasRemoved);
+            else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                raiseCollectionChanged();
+        }
+
+        /// <summary>
+        /// Check if all items in a supplied collection is in this bag
+        /// (counting multiplicities). 
+        /// </summary>
+        /// <param name="items">The items to look for.</param>
+        /// <returns>True if all items are found.</returns>
+        public virtual bool ContainsAll(SCG.IEnumerable<T> items)
+        {
+            HashBag<T> res = new HashBag<T>(itemequalityComparer);
+
+            foreach (T item in items)
+                if (res.ContainsCount(item) < ContainsCount(item))
+                    res.Add(item);
+                else
+                    return false;
+
+            return true;
+        }
+
+
+        /// <summary>
+        /// Create an array containing all items in this bag (in enumeration order).
+        /// </summary>
+        /// <returns>The array</returns>
+        public override T[] ToArray()
+        {
+            T[] res = new T[size];
+            int ind = 0;
+
+            foreach (KeyValuePair<T, int> p in dict)
+                for (int i = 0; i < p.Value; i++)
+                    res[ind++] = p.Key;
+
+            return res;
+        }
+
+
+        /// <summary>
+        /// Count the number of times an item is in this set.
+        /// </summary>
+        /// <param name="item">The item to look for.</param>
+        /// <returns>The count</returns>
+        public virtual int ContainsCount(T item)
+        {
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+            if (dict.Find(ref p))
+                return p.Value;
+
+            return 0;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<T> UniqueItems() { return new DropMultiplicity<T>(dict); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+        {
+            return new GuardedCollectionValue<KeyValuePair<T, int>>(dict);
+        }
+
+        /// <summary>
+        /// Remove all copies of item from this set.
+        /// </summary>
+        /// <param name="item">The item to remove</param>
+        public virtual void RemoveAllCopies(T item)
+        {
+            updatecheck();
+
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+            if (dict.Find(ref p))
+            {
+                size -= p.Value;
+                dict.Remove(p);
+                if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+                    raiseItemsRemoved(p.Key, p.Value);
+                if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                    raiseCollectionChanged();
+            }
+        }
+
+        #endregion
+
+        #region ICollection<T> Members
+
+
+        /// <summary>
+        /// Copy the items of this bag to part of an array.
+        /// <exception cref="ArgumentOutOfRangeException"/> if i is negative.
+        /// <exception cref="ArgumentException"/> if the array does not have room for the items.
+        /// </summary>
+        /// <param name="array">The array to copy to</param>
+        /// <param name="index">The starting index.</param>
+        public override void CopyTo(T[] array, int index)
+        {
+            if (index < 0 || index + Count > array.Length)
+                throw new ArgumentOutOfRangeException();
+
+            foreach (KeyValuePair<T, int> p in dict)
+                for (int j = 0; j < p.Value; j++)
+                    array[index++] = p.Key;
+        }
+
+        #endregion
+
+        #region IExtensible<T> Members
+
+        /// <summary>
+        /// Report if this is a set collection.
+        /// </summary>
+        /// <value>Always true</value>
+        public virtual bool AllowsDuplicates { get { return true; } }
+
+        /// <summary>
+        /// By convention this is true for any collection with set semantics.
+        /// </summary>
+        /// <value>True if only one representative of a group of equal items 
+        /// is kept in the collection together with the total count.</value>
+        public virtual bool DuplicatesByCounting { get { return true; } }
+
+        /// <summary>
+        /// Add an item to this bag.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
+        /// <returns>Always true</returns>
+        public virtual bool Add(T item)
+        {
+            updatecheck();
+            add(ref item);
+            if (ActiveEvents != 0)
+                raiseForAdd(item);
+            return true;
+        }
+
+        /// <summary>
+        /// Add an item to this bag.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
+        void SCG.ICollection<T>.Add(T item)
+        {
+            Add(item);
+        }
+
+        private void add(ref T item)
+        {
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 1);
+            if (dict.Find(ref p))
+            {
+                p.Value++;
+                dict.Update(p);
+                item = p.Key;
+            }
+            else
+                dict.Add(p);
+            size++;
+        }
+
+        /// <summary>
+        /// Add the elements from another collection with a more specialized item type 
+        /// to this collection. 
+        /// </summary>
+        /// <param name="items">The items to add</param>
+        public virtual void AddAll(SCG.IEnumerable<T> items)
+        {
+            updatecheck();
+#warning We could easily raise bag events
+            bool mustRaiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;
+            CircularQueue<T> wasAdded = mustRaiseAdded ? new CircularQueue<T>() : null;
+            bool wasChanged = false;
+            foreach (T item in items)
+            {
+                T jtem = item;
+                add(ref jtem);
+                wasChanged = true;
+                if (mustRaiseAdded)
+                    wasAdded.Enqueue(jtem);
+            }
+            if (!wasChanged)
+                return;
+            if (mustRaiseAdded)
+                foreach (T item in wasAdded)
+                    raiseItemsAdded(item, 1);
+            if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+                raiseCollectionChanged();
+        }
+
+        #endregion
+
+        #region IEnumerable<T> Members
+
+
+        /// <summary>
+        /// Choose some item of this collection. 
+        /// </summary>
+        /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+        /// <returns></returns>
+        public override T Choose()
+        {
+            return dict.Choose().Key;
+        }
+
+        /// <summary>
+        /// Create an enumerator for this bag.
+        /// </summary>
+        /// <returns>The enumerator</returns>
+        public override SCG.IEnumerator<T> GetEnumerator()
+        {
+            int left;
+            int mystamp = stamp;
+
+            foreach (KeyValuePair<T, int> p in dict)
+            {
+                left = p.Value;
+                while (left > 0)
+                {
+                    if (mystamp != stamp)
+                        throw new CollectionModifiedException();
+
+                    left--;
+                    yield return p.Key;
+                }
+            }
+        }
+        #endregion
+
+        #region Diagnostics
+        /// <summary>
+        /// Test internal structure of data (invariants)
+        /// </summary>
+        /// <returns>True if pass</returns>
+        public virtual bool Check()
+        {
+            bool retval = dict.Check();
+            int count = 0;
+
+            foreach (KeyValuePair<T, int> p in dict)
+                count += p.Value;
+
+            if (count != size)
+            {
+                Logger.Log(string.Format("count({0}) != size({1})", count, size));
+                retval = false;
+            }
+
+            return retval;
+        }
+        #endregion
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/5f198526/src/Lucene.Net.Tests/core/Support/C5/Sorting.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Support/C5/Sorting.cs b/src/Lucene.Net.Tests/core/Support/C5/Sorting.cs
new file mode 100644
index 0000000..58a16ae
--- /dev/null
+++ b/src/Lucene.Net.Tests/core/Support/C5/Sorting.cs
@@ -0,0 +1,235 @@
+\ufeff/*
+ Copyright (c) 2003-2016 Niels Kokholm, Peter Sestoft, and Rasmus Lystr�m
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+using System;
+using SCG = System.Collections.Generic;
+namespace Lucene.Net.Support.C5
+{
+    /// <summary>
+    /// A utility class with functions for sorting arrays with respect to an IComparer&lt;T&gt;
+    /// </summary>
+    [Serializable]
+    public class Sorting
+    {
+        Sorting() { }
+
+        /// <summary>
+        /// Sort part of array in place using IntroSort
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>
+        /// and <code>count</code> arguments does not describe a valid range.</exception>
+        /// <param name="array">Array to sort</param>
+        /// <param name="start">Index of first position to sort</param>
+        /// <param name="count">Number of elements to sort</param>
+        /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>
+        public static void IntroSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)
+        {
+            if (start < 0 || count < 0 || start + count > array.Length)
+                throw new ArgumentOutOfRangeException();
+            new Sorter<T>(array, comparer).IntroSort(start, start + count);
+        }
+
+        /// <summary>
+        /// Sort an array in place using IntroSort and default comparer
+        /// </summary>
+        /// <exception cref="NotComparableException">If T is not comparable</exception>
+        /// <param name="array">Array to sort</param>
+        public static void IntroSort<T>(T[] array)
+        {
+            new Sorter<T>(array, SCG.Comparer<T>.Default).IntroSort(0, array.Length);
+        }
+
+
+        /// <summary>
+        /// Sort part of array in place using Insertion Sort
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>
+        /// and <code>count</code> arguments does not describe a valid range.</exception>
+        /// <param name="array">Array to sort</param>
+        /// <param name="start">Index of first position to sort</param>
+        /// <param name="count">Number of elements to sort</param>
+        /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>
+        public static void InsertionSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)
+        {
+            if (start < 0 || count < 0 || start + count > array.Length)
+                throw new ArgumentOutOfRangeException();
+            new Sorter<T>(array, comparer).InsertionSort(start, start + count);
+        }
+
+
+        /// <summary>
+        /// Sort part of array in place using Heap Sort
+        /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>
+        /// and <code>count</code> arguments does not describe a valid range.</exception>
+        /// <param name="array">Array to sort</param>
+        /// <param name="start">Index of first position to sort</param>
+        /// <param name="count">Number of elements to sort</param>
+        /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>
+        public static void HeapSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)
+        {
+            if (start < 0 || count < 0 || start + count > array.Length)
+                throw new ArgumentOutOfRangeException();
+            new Sorter<T>(array, comparer).HeapSort(start, start + count);
+        }
+
+        [Serializable]
+        class Sorter<T>
+        {
+            T[] a;
+
+            SCG.IComparer<T> c;
+
+
+            internal Sorter(T[] a, SCG.IComparer<T> c) { this.a = a; this.c = c; }
+
+
+            internal void IntroSort(int f, int b)
+            {
+                if (b - f > 31)
+                {
+                    int depth_limit = (int)Math.Floor(2.5 * Math.Log(b - f, 2));
+
+                    introSort(f, b, depth_limit);
+                }
+                else
+                    InsertionSort(f, b);
+            }
+
+
+            private void introSort(int f, int b, int depth_limit)
+            {
+                const int size_threshold = 14;//24;
+
+                if (depth_limit-- == 0)
+                    HeapSort(f, b);
+                else if (b - f <= size_threshold)
+                    InsertionSort(f, b);
+                else
+                {
+                    int p = partition(f, b);
+
+                    introSort(f, p, depth_limit);
+                    introSort(p, b, depth_limit);
+                }
+            }
+
+
+            private int compare(T i1, T i2) { return c.Compare(i1, i2); }
+
+
+            private int partition(int f, int b)
+            {
+                int bot = f, mid = (b + f) / 2, top = b - 1;
+                T abot = a[bot], amid = a[mid], atop = a[top];
+
+                if (compare(abot, amid) < 0)
+                {
+                    if (compare(atop, abot) < 0)//atop<abot<amid
+                    { a[top] = amid; amid = a[mid] = abot; a[bot] = atop; }
+                    else if (compare(atop, amid) < 0) //abot<=atop<amid
+                    { a[top] = amid; amid = a[mid] = atop; }
+                    //else abot<amid<=atop
+                }
+                else
+                {
+                    if (compare(amid, atop) > 0) //atop<amid<=abot
+                    { a[bot] = atop; a[top] = abot; }
+                    else if (compare(abot, atop) > 0) //amid<=atop<abot
+                    { a[bot] = amid; amid = a[mid] = atop; a[top] = abot; }
+                    else //amid<=abot<=atop
+                    { a[bot] = amid; amid = a[mid] = abot; }
+                }
+
+                int i = bot, j = top;
+
+                while (true)
+                {
+                    while (compare(a[++i], amid) < 0) ;
+
+                    while (compare(amid, a[--j]) < 0) ;
+
+                    if (i < j)
+                    {
+                        T tmp = a[i]; a[i] = a[j]; a[j] = tmp;
+                    }
+                    else
+                        return i;
+                }
+            }
+
+
+            internal void InsertionSort(int f, int b)
+            {
+                for (int j = f + 1; j < b; j++)
+                {
+                    T key = a[j], other;
+                    int i = j - 1;
+
+                    if (c.Compare(other = a[i], key) > 0)
+                    {
+                        a[j] = other;
+                        while (i > f && c.Compare(other = a[i - 1], key) > 0) { a[i--] = other; }
+
+                        a[i] = key;
+                    }
+                }
+            }
+
+
+            internal void HeapSort(int f, int b)
+            {
+                for (int i = (b + f) / 2; i >= f; i--) heapify(f, b, i);
+
+                for (int i = b - 1; i > f; i--)
+                {
+                    T tmp = a[f]; a[f] = a[i]; a[i] = tmp;
+                    heapify(f, i, f);
+                }
+            }
+
+
+            private void heapify(int f, int b, int i)
+            {
+                T pv = a[i], lv, rv, max = pv;
+                int j = i, maxpt = j;
+
+                while (true)
+                {
+                    int l = 2 * j - f + 1, r = l + 1;
+
+                    if (l < b && compare(lv = a[l], max) > 0) { maxpt = l; max = lv; }
+
+                    if (r < b && compare(rv = a[r], max) > 0) { maxpt = r; max = rv; }
+
+                    if (maxpt == j)
+                        break;
+
+                    a[j] = max;
+                    max = pv;
+                    j = maxpt;
+                }
+
+                if (j > i)
+                    a[j] = pv;
+            }
+        }
+    }
+}
\ No newline at end of file


[36/58] [abbrv] lucenenet git commit: Fixed namespace issue in Join.ToParentBlockJoinCollector

Posted by ni...@apache.org.
Fixed namespace issue in Join.ToParentBlockJoinCollector


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

Branch: refs/heads/grouping
Commit: b689479e06857cd40106e632136d9b1dd7c3cd4d
Parents: 9d72bcb
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Thu Oct 27 18:45:26 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:54 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Join/ToParentBlockJoinCollector.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b689479e/src/Lucene.Net.Join/ToParentBlockJoinCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Join/ToParentBlockJoinCollector.cs b/src/Lucene.Net.Join/ToParentBlockJoinCollector.cs
index 85d8ee8..ca870ec 100644
--- a/src/Lucene.Net.Join/ToParentBlockJoinCollector.cs
+++ b/src/Lucene.Net.Join/ToParentBlockJoinCollector.cs
@@ -3,9 +3,9 @@ using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
-using Lucene.Net.Grouping;
 using Lucene.Net.Index;
 using Lucene.Net.Search;
+using Lucene.Net.Search.Grouping;
 using Lucene.Net.Support;
 using Lucene.Net.Util;
 


[23/58] [abbrv] lucenenet git commit: HACK: (3rd) Added stubs for all tests subclasses of abstract test classes (with [Test] attributes) and commented the [Test] attributes in the abstract classes to keep the tests from running in the wrong context.

Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs b/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
index e90b365..e49ed8d 100644
--- a/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Ext/TestExtendableQueryParser.cs
@@ -141,5 +141,374 @@ namespace Lucene.Net.QueryParsers.Ext
                 assertEquals("foo & bar", tquery.Term.Text());
             }
         }
+
+
+        #region TestQueryParser
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDefaultOperator()
+        {
+            base.TestDefaultOperator();
+        }
+
+        [Test]
+        public override void TestProtectedCtors()
+        {
+            base.TestProtectedCtors();
+        }
+
+        [Test]
+        public override void TestFuzzySlopeExtendability()
+        {
+            base.TestFuzzySlopeExtendability();
+        }
+
+        [Test]
+        public override void TestStarParsing()
+        {
+            base.TestStarParsing();
+        }
+
+        [Test]
+        public override void TestCustomQueryParserWildcard()
+        {
+            base.TestCustomQueryParserWildcard();
+        }
+
+        [Test]
+        public override void TestCustomQueryParserFuzzy()
+        {
+            base.TestCustomQueryParserFuzzy();
+        }
+
+        [Test]
+        public override void TestNewFieldQuery()
+        {
+            base.TestNewFieldQuery();
+        }
+
+        /// <summary>
+        /// simple synonyms test
+        /// </summary>
+        [Test]
+        public override void TestSynonyms()
+        {
+            base.TestSynonyms();
+        }
+
+        /// <summary>
+        /// forms multiphrase query
+        /// </summary>
+        [Test]
+        public override void TestSynonymsPhrase()
+        {
+            base.TestSynonymsPhrase();
+        }
+
+        /// <summary>
+        /// simple CJK synonym test
+        /// </summary>
+        [Test]
+        public override void TestCJKSynonym()
+        {
+            base.TestCJKSynonym();
+        }
+
+        /// <summary>
+        /// synonyms with default OR operator 
+        /// </summary>
+        [Test]
+        public override void TestCJKSynonymsOR()
+        {
+            base.TestCJKSynonymsOR();
+        }
+
+        /// <summary>
+        /// more complex synonyms with default OR operator
+        /// </summary>
+        [Test]
+        public override void TestCJKSynonymsOR2()
+        {
+            base.TestCJKSynonymsOR2();
+        }
+
+        /// <summary>
+        /// synonyms with default AND operator
+        /// </summary>
+        [Test]
+        public override void TestCJKSynonymsAND()
+        {
+            base.TestCJKSynonymsAND();
+        }
+
+        /// <summary>
+        /// more complex synonyms with default AND operator
+        /// </summary>
+        [Test]
+        public override void TestCJKSynonymsAND2()
+        {
+            base.TestCJKSynonymsAND2();
+        }
+
+        [Test]
+        public override void TestCJKSynonymsPhrase()
+        {
+            base.TestCJKSynonymsPhrase();
+        }
+
+        #endregion
+
+        #region QueryParserTestBase
+        // LUCENENET NOTE: Tests in a base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestCJK()
+        {
+            base.TestCJK();
+        }
+
+        [Test]
+        public override void TestCJKTerm()
+        {
+            base.TestCJKTerm();
+        }
+
+        [Test]
+        public override void TestCJKBoostedTerm()
+        {
+            base.TestCJKBoostedTerm();
+        }
+
+        [Test]
+        public override void TestCJKPhrase()
+        {
+            base.TestCJKPhrase();
+        }
+
+        [Test]
+        public override void TestCJKBoostedPhrase()
+        {
+            base.TestCJKBoostedPhrase();
+        }
+
+        [Test]
+        public override void TestCJKSloppyPhrase()
+        {
+            base.TestCJKSloppyPhrase();
+        }
+
+        [Test]
+        public override void TestAutoGeneratePhraseQueriesOn()
+        {
+            base.TestAutoGeneratePhraseQueriesOn();
+        }
+
+        [Test]
+        public override void TestSimple()
+        {
+            base.TestSimple();
+        }
+
+        [Test]
+        public override void TestOperatorVsWhitespace()
+        {
+            base.TestOperatorVsWhitespace();
+        }
+
+        [Test]
+        public override void TestPunct()
+        {
+            base.TestPunct();
+        }
+
+        [Test]
+        public override void TestSlop()
+        {
+            base.TestSlop();
+        }
+
+        [Test]
+        public override void TestNumber()
+        {
+            base.TestNumber();
+        }
+
+        [Test]
+        public override void TestWildcard()
+        {
+            base.TestWildcard();
+        }
+
+        [Test]
+        public override void TestLeadingWildcardType()
+        {
+            base.TestLeadingWildcardType();
+        }
+
+        [Test]
+        public override void TestQPA()
+        {
+            base.TestQPA();
+        }
+
+        [Test]
+        public override void TestRange()
+        {
+            base.TestRange();
+        }
+
+        [Test]
+        public override void TestRangeWithPhrase()
+        {
+            base.TestRangeWithPhrase();
+        }
+
+        [Test]
+        public override void TestDateRange()
+        {
+            base.TestDateRange();
+        }
+
+        [Test]
+        public override void TestEscaped()
+        {
+            base.TestEscaped();
+        }
+
+        [Test]
+        public override void TestEscapedVsQuestionMarkAsWildcard()
+        {
+            base.TestEscapedVsQuestionMarkAsWildcard();
+        }
+
+        [Test]
+        public override void TestQueryStringEscaping()
+        {
+            base.TestQueryStringEscaping();
+        }
+
+        [Test]
+        public override void TestTabNewlineCarriageReturn()
+        {
+            base.TestTabNewlineCarriageReturn();
+        }
+
+        [Test]
+        public override void TestSimpleDAO()
+        {
+            base.TestSimpleDAO();
+        }
+
+        [Test]
+        public override void TestBoost()
+        {
+            base.TestBoost();
+        }
+
+        [Test]
+        public override void TestException()
+        {
+            base.TestException();
+        }
+
+        [Test]
+        public override void TestBooleanQuery()
+        {
+            base.TestBooleanQuery();
+        }
+
+        [Test]
+        public override void TestPrecedence()
+        {
+            base.TestPrecedence();
+        }
+
+        [Test]
+        public override void TestEscapedWildcard()
+        {
+            base.TestEscapedWildcard();
+        }
+
+        [Test]
+        public override void TestRegexps()
+        {
+            base.TestRegexps();
+        }
+
+        [Test]
+        public override void TestStopwords()
+        {
+            base.TestStopwords();
+        }
+
+        [Test]
+        public override void TestPositionIncrement()
+        {
+            base.TestPositionIncrement();
+        }
+
+        [Test]
+        public override void TestMatchAllDocs()
+        {
+            base.TestMatchAllDocs();
+        }
+
+        // LUCENE-2002: make sure defaults for StandardAnalyzer's
+        // enableStopPositionIncr & QueryParser's enablePosIncr
+        // "match"
+        [Test]
+        public override void TestPositionIncrements()
+        {
+            base.TestPositionIncrements();
+        }
+
+        [Test]
+        public override void TestCollatedRange()
+        {
+            base.TestCollatedRange();
+        }
+
+        [Test]
+        public override void TestDistanceAsEditsParsing()
+        {
+            base.TestDistanceAsEditsParsing();
+        }
+
+        [Test]
+        public override void TestPhraseQueryToString()
+        {
+            base.TestPhraseQueryToString();
+        }
+
+        [Test]
+        public override void TestParseWildcardAndPhraseQueries()
+        {
+            base.TestParseWildcardAndPhraseQueries();
+        }
+
+        [Test]
+        public override void TestPhraseQueryPositionIncrements()
+        {
+            base.TestPhraseQueryPositionIncrements();
+        }
+
+        [Test]
+        public override void TestMatchAllQueryParsing()
+        {
+            base.TestMatchAllQueryParsing();
+        }
+
+        [Test]
+        public override void TestNestedAndClausesFoo()
+        {
+            base.TestNestedAndClausesFoo();
+        }
+
+        #endregion
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
index 37f00e2..9dcfcde 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestCompressionMode.cs
@@ -88,7 +88,7 @@ namespace Lucene.Net.Codecs.Compressing
             return Arrays.CopyOfRange(bytes.Bytes, bytes.Offset, bytes.Offset + bytes.Length);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestDecompress()
         {
             int iterations = AtLeast(10);
@@ -103,7 +103,7 @@ namespace Lucene.Net.Codecs.Compressing
             }
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestPartialDecompress()
         {
             int iterations = AtLeast(10);
@@ -139,19 +139,19 @@ namespace Lucene.Net.Codecs.Compressing
             return compressed;
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestEmptySequence()
         {
             Test(new byte[0]);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestShortSequence()
         {
             Test(new[] { (byte)Random().Next(256) });
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestIncompressible()
         {
             var decompressed = new byte[RandomInts.NextIntBetween(Random(), 20, 256)];
@@ -162,7 +162,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestConstant()
         {
             var decompressed = new byte[TestUtil.NextInt(Random(), 1, 10000)];
@@ -170,7 +170,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestLUCENE5201()
         {
             sbyte[] data = { 14, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 72, 14, 72, 14, 85, 3, 72, 14, 72, 14, 72, 14, 72, 14, 72, 14, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 85, 3, 72, 14, 50, 64, 0, 46, -1, 0, 0, 0, 29, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 50, 64, 0, 47, -105, 0, 0, 0, 30, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, -97, 6, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68
 , -113, 0, 120, 64, 0, 48, 4, 0, 0, 0, 31, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 24, 32, 34, 124, 0, 120, 64, 0, 48, 80, 0, 0, 0, 31, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 
 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 7
 2, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 72, 34, 72, 29, 72, 37, 72, 35, 72, 45, 72, 23, 72, 46, 72, 20, 72, 40, 72, 33, 72, 25, 72, 39, 72, 38, 72, 26, 72, 28, 72, 42, 72, 24, 72, 27, 72, 36, 72, 41, 72, 32, 72, 18, 72, 30, 72, 22, 72, 31, 72, 43, 72, 19, 50, 64, 0, 49, 20, 0, 0, 0, 32, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 50, 64, 0, 50, 53, 0, 0, 0, 34, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0
 , 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 50, 64, 0, 51, 85, 0, 0, 0, 36, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, -97, 5, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 50, -64, 0, 51, -45, 0, 0, 0, 37, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, -9
 7, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -113, 0, 2, 3, -97, 6, 0, 68, -113, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 2, 3, 85, 8, -113, 0, 68, -97, 3, 0, 120, 64, 0, 52, -88, 0, 0, 0, 39, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 72, 13, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, 72, 13, 85, 5, 72, 13, -19, -24, -101, -35 };

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
index feb57d0..334ae8d 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/AbstractTestLZ4CompressionMode.cs
@@ -88,7 +88,7 @@ namespace Lucene.Net.Codecs.Compressing
             return compressed;
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestShortLiteralsAndMatchs()
         {
             // literals and matchs lengths <= 15
@@ -96,7 +96,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestLongMatchs()
         {
             // match length >= 20
@@ -108,7 +108,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestLongLiterals()
         {
             // long literals (length >= 16) which are not the last literals
@@ -120,7 +120,7 @@ namespace Lucene.Net.Codecs.Compressing
             Test(decompressed);
         }
 
-        [Test]
+        // [Test] // LUCENENET NOTE: For now, we are overriding this test in every subclass to pull it into the right context for the subclass
         public virtual void TestMatchRightBeforeLastLiterals()
         {
             Test(new byte[] { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 5 });

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
index acdf73c..998b942 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingStoredFieldsFormat.cs
@@ -100,5 +100,94 @@ namespace Lucene.Net.Codecs.Compressing
                 this.OuterInstance = outerInstance;
             }
         }
+
+
+        #region BaseStoredFieldsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestRandomStoredFields()
+        {
+            base.TestRandomStoredFields();
+        }
+
+        [Test]
+        // LUCENE-1727: make sure doc fields are stored in order
+        public override void TestStoredFieldsOrder()
+        {
+            base.TestStoredFieldsOrder();
+        }
+
+        [Test]
+        // LUCENE-1219
+        public override void TestBinaryFieldOffsetLength()
+        {
+            base.TestBinaryFieldOffsetLength();
+        }
+
+        [Test]
+        public override void TestNumericField()
+        {
+            base.TestNumericField();
+        }
+
+        [Test]
+        public override void TestIndexedBit()
+        {
+            base.TestIndexedBit();
+        }
+
+        [Test]
+        public override void TestReadSkip()
+        {
+            base.TestReadSkip();
+        }
+
+        [Test]
+        public override void TestEmptyDocs()
+        {
+            base.TestEmptyDocs();
+        }
+
+        [Test]
+        public override void TestConcurrentReads()
+        {
+            base.TestConcurrentReads();
+        }
+
+        [Test]
+        public override void TestWriteReadMerge()
+        {
+            base.TestWriteReadMerge();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestBigDocuments()
+        {
+            base.TestBigDocuments();
+        }
+
+        [Test]
+        public override void TestBulkMergeWithDeletes()
+        {
+            base.TestBulkMergeWithDeletes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
index 90b06cf..709af74 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestCompressingTermVectorsFormat.cs
@@ -84,5 +84,72 @@ namespace Lucene.Net.Codecs.Compressing
             iw.Dispose();
             dir.Dispose();
         }
+
+
+        #region BaseTermVectorsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        // only one doc with vectors
+        public override void TestRareVectors()
+        {
+            base.TestRareVectors();
+        }
+
+        [Test]
+        public override void TestHighFreqs()
+        {
+            base.TestHighFreqs();
+        }
+
+        [Test]
+        public override void TestLotsOfFields()
+        {
+            base.TestLotsOfFields();
+        }
+
+        [Test]
+        // different options for the same field
+        public override void TestMixedOptions()
+        {
+            base.TestMixedOptions();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test, Timeout(30000)]
+        public override void TestMerge()
+        {
+            base.TestMerge();
+        }
+
+        [Test]
+        // run random tests from different threads to make sure the per-thread clones
+        // don't share mutable data
+        public override void TestClone()
+        {
+            base.TestClone();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
index dd7d708..6a74a51 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastCompressionMode.cs
@@ -28,5 +28,86 @@ namespace Lucene.Net.Codecs.Compressing
             base.SetUp();
             Mode = CompressionMode.FAST;
         }
+
+
+        #region AbstractTestLZ4CompressionMode
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestShortLiteralsAndMatchs()
+        {
+            base.TestShortLiteralsAndMatchs();
+        }
+
+        [Test]
+        public override void TestLongMatchs()
+        {
+            base.TestLongMatchs();
+        }
+
+        [Test]
+        public override void TestLongLiterals()
+        {
+            base.TestLongLiterals();
+        }
+
+        [Test]
+        public override void TestMatchRightBeforeLastLiterals()
+        {
+            base.TestMatchRightBeforeLastLiterals();
+        }
+
+        #endregion
+
+        #region AbstractTestCompressionMode
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDecompress()
+        {
+            base.TestDecompress();
+        }
+
+        [Test]
+        public override void TestPartialDecompress()
+        {
+            base.TestPartialDecompress();
+        }
+
+        [Test]
+        public override void TestEmptySequence()
+        {
+            base.TestEmptySequence();
+        }
+
+        [Test]
+        public override void TestShortSequence()
+        {
+            base.TestShortSequence();
+        }
+
+        [Test]
+        public override void TestIncompressible()
+        {
+            base.TestIncompressible();
+        }
+
+        [Test]
+        public override void TestConstant()
+        {
+            base.TestConstant();
+        }
+
+        [Test]
+        public override void TestLUCENE5201()
+        {
+            base.TestLUCENE5201();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
index d7fc0b0..b90a582 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestFastDecompressionMode.cs
@@ -38,5 +38,86 @@ namespace Lucene.Net.Codecs.Compressing
             Assert.IsTrue(compressed.Length <= compressed2.Length);
             return compressed;
         }
+
+
+        #region AbstractTestLZ4CompressionMode
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestShortLiteralsAndMatchs()
+        {
+            base.TestShortLiteralsAndMatchs();
+        }
+
+        [Test]
+        public override void TestLongMatchs()
+        {
+            base.TestLongMatchs();
+        }
+
+        [Test]
+        public override void TestLongLiterals()
+        {
+            base.TestLongLiterals();
+        }
+
+        [Test]
+        public override void TestMatchRightBeforeLastLiterals()
+        {
+            base.TestMatchRightBeforeLastLiterals();
+        }
+
+        #endregion
+
+        #region AbstractTestCompressionMode
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDecompress()
+        {
+            base.TestDecompress();
+        }
+
+        [Test]
+        public override void TestPartialDecompress()
+        {
+            base.TestPartialDecompress();
+        }
+
+        [Test]
+        public override void TestEmptySequence()
+        {
+            base.TestEmptySequence();
+        }
+
+        [Test]
+        public override void TestShortSequence()
+        {
+            base.TestShortSequence();
+        }
+
+        [Test]
+        public override void TestIncompressible()
+        {
+            base.TestIncompressible();
+        }
+
+        [Test]
+        public override void TestConstant()
+        {
+            base.TestConstant();
+        }
+
+        [Test]
+        public override void TestLUCENE5201()
+        {
+            base.TestLUCENE5201();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
index eebcda1..679d1f0 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Compressing/TestHighCompressionMode.cs
@@ -28,5 +28,55 @@ namespace Lucene.Net.Codecs.Compressing
             base.SetUp();
             Mode = CompressionMode.HIGH_COMPRESSION;
         }
+
+
+        #region AbstractTestCompressionMode
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDecompress()
+        {
+            base.TestDecompress();
+        }
+
+        [Test]
+        public override void TestPartialDecompress()
+        {
+            base.TestPartialDecompress();
+        }
+
+        [Test]
+        public override void TestEmptySequence()
+        {
+            base.TestEmptySequence();
+        }
+
+        [Test]
+        public override void TestShortSequence()
+        {
+            base.TestShortSequence();
+        }
+
+        [Test]
+        public override void TestIncompressible()
+        {
+            base.TestIncompressible();
+        }
+
+        [Test]
+        public override void TestConstant()
+        {
+            base.TestConstant();
+        }
+
+        [Test]
+        public override void TestLUCENE5201()
+        {
+            base.TestLUCENE5201();
+        }
+        #endregion
+
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
index cf1bafc..0ab9a7b 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xPostingsFormat.cs
@@ -42,5 +42,68 @@ namespace Lucene.Net.Codecs.Lucene3x
                 return Codec_Renamed;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
index b28f86a..d3d0889 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xStoredFieldsFormat.cs
@@ -52,5 +52,89 @@ namespace Lucene.Net.Codecs.Lucene3x
             // for 3.x: we currently cannot take an index with existing 4.x segments
             // and merge into newly formed 3.x segments.
         }
+
+
+
+        #region BaseStoredFieldsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestRandomStoredFields()
+        {
+            base.TestRandomStoredFields();
+        }
+
+        [Test]
+        // LUCENE-1727: make sure doc fields are stored in order
+        public override void TestStoredFieldsOrder()
+        {
+            base.TestStoredFieldsOrder();
+        }
+
+        [Test]
+        // LUCENE-1219
+        public override void TestBinaryFieldOffsetLength()
+        {
+            base.TestBinaryFieldOffsetLength();
+        }
+
+        [Test]
+        public override void TestNumericField()
+        {
+            base.TestNumericField();
+        }
+
+        [Test]
+        public override void TestIndexedBit()
+        {
+            base.TestIndexedBit();
+        }
+
+        [Test]
+        public override void TestReadSkip()
+        {
+            base.TestReadSkip();
+        }
+
+        [Test]
+        public override void TestEmptyDocs()
+        {
+            base.TestEmptyDocs();
+        }
+
+        [Test]
+        public override void TestConcurrentReads()
+        {
+            base.TestConcurrentReads();
+        }
+
+        [Test, Timeout(120000)]
+        public override void TestBigDocuments()
+        {
+            base.TestBigDocuments();
+        }
+
+        [Test]
+        public override void TestBulkMergeWithDeletes()
+        {
+            base.TestBulkMergeWithDeletes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
index 1cf090b..5756752 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene3x/TestLucene3xTermVectorsFormat.cs
@@ -46,5 +46,72 @@ namespace Lucene.Net.Codecs.Lucene3x
         {
             return ValidOptions(Options.NONE, Options.POSITIONS_AND_OFFSETS);
         }
+
+
+        #region BaseTermVectorsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        // only one doc with vectors
+        public override void TestRareVectors()
+        {
+            base.TestRareVectors();
+        }
+
+        [Test]
+        public override void TestHighFreqs()
+        {
+            base.TestHighFreqs();
+        }
+
+        [Test]
+        public override void TestLotsOfFields()
+        {
+            base.TestLotsOfFields();
+        }
+
+        [Test, Timeout(300000)]
+        // different options for the same field
+        public override void TestMixedOptions()
+        {
+            base.TestMixedOptions();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestMerge()
+        {
+            base.TestMerge();
+        }
+
+        [Test]
+        // run random tests from different threads to make sure the per-thread clones
+        // don't share mutable data
+        public override void TestClone()
+        {
+            base.TestClone();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
index 9ee39e7..3686767 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40DocValuesFormat.cs
@@ -50,5 +50,506 @@ namespace Lucene.Net.Codecs.Lucene40
         {
             return false;
         }
+
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
index c7f7f07..0d3666d 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40PostingsFormat.cs
@@ -44,5 +44,68 @@ namespace Lucene.Net.Codecs.Lucene40
                 return new Lucene40RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
index 4e57234..4e3bebf 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40StoredFieldsFormat.cs
@@ -41,5 +41,94 @@ namespace Lucene.Net.Codecs.Lucene40
                 return new Lucene40RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
+
+
+        #region BaseStoredFieldsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestRandomStoredFields()
+        {
+            base.TestRandomStoredFields();
+        }
+
+        [Test]
+        // LUCENE-1727: make sure doc fields are stored in order
+        public override void TestStoredFieldsOrder()
+        {
+            base.TestStoredFieldsOrder();
+        }
+
+        [Test]
+        // LUCENE-1219
+        public override void TestBinaryFieldOffsetLength()
+        {
+            base.TestBinaryFieldOffsetLength();
+        }
+
+        [Test]
+        public override void TestNumericField()
+        {
+            base.TestNumericField();
+        }
+
+        [Test]
+        public override void TestIndexedBit()
+        {
+            base.TestIndexedBit();
+        }
+
+        [Test]
+        public override void TestReadSkip()
+        {
+            base.TestReadSkip();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestEmptyDocs()
+        {
+            base.TestEmptyDocs();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestConcurrentReads()
+        {
+            base.TestConcurrentReads();
+        }
+
+        [Test]
+        public override void TestWriteReadMerge()
+        {
+            base.TestWriteReadMerge();
+        }
+
+        [Test, Timeout(80000)]
+        public override void TestBigDocuments()
+        {
+            base.TestBigDocuments();
+        }
+
+        [Test]
+        public override void TestBulkMergeWithDeletes()
+        {
+            base.TestBulkMergeWithDeletes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
index 342d7ce..9a6e544 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene40/TestLucene40TermVectorsFormat.cs
@@ -41,5 +41,72 @@ namespace Lucene.Net.Codecs.Lucene40
                 return new Lucene40RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
+
+
+        #region BaseTermVectorsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        // only one doc with vectors
+        public override void TestRareVectors()
+        {
+            base.TestRareVectors();
+        }
+
+        [Test]
+        public override void TestHighFreqs()
+        {
+            base.TestHighFreqs();
+        }
+
+        [Test]
+        public override void TestLotsOfFields()
+        {
+            base.TestLotsOfFields();
+        }
+
+        [Test, Timeout(300000)]
+        // different options for the same field
+        public override void TestMixedOptions()
+        {
+            base.TestMixedOptions();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        [Test]
+        public override void TestMerge()
+        {
+            base.TestMerge();
+        }
+
+        [Test]
+        // run random tests from different threads to make sure the per-thread clones
+        // don't share mutable data
+        public override void TestClone()
+        {
+            base.TestClone();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
index 201eaf6..fb309a5 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestBlockPostingsFormat.cs
@@ -1,3 +1,5 @@
+using NUnit.Framework;
+
 namespace Lucene.Net.Codecs.Lucene41
 {
     /*
@@ -34,5 +36,68 @@ namespace Lucene.Net.Codecs.Lucene41
                 return Codec_Renamed;
             }
         }
+
+
+        #region BasePostingsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestDocsOnly()
+        {
+            base.TestDocsOnly();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqs()
+        {
+            base.TestDocsAndFreqs();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositions()
+        {
+            base.TestDocsAndFreqsAndPositions();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndPayloads();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsets()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsets();
+        }
+
+        [Test]
+        public override void TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads()
+        {
+            base.TestDocsAndFreqsAndPositionsAndOffsetsAndPayloads();
+        }
+
+        [Test]
+        public override void TestRandom()
+        {
+            base.TestRandom();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
index 4259478..bcd5a49 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene41/TestLucene41StoredFieldsFormat.cs
@@ -40,5 +40,94 @@ namespace Lucene.Net.Codecs.Lucene41
                 return new Lucene41RWCodec(OLD_FORMAT_IMPERSONATION_IS_ACTIVE);
             }
         }
+
+
+        #region BaseStoredFieldsFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestRandomStoredFields()
+        {
+            base.TestRandomStoredFields();
+        }
+
+        [Test]
+        // LUCENE-1727: make sure doc fields are stored in order
+        public override void TestStoredFieldsOrder()
+        {
+            base.TestStoredFieldsOrder();
+        }
+
+        [Test]
+        // LUCENE-1219
+        public override void TestBinaryFieldOffsetLength()
+        {
+            base.TestBinaryFieldOffsetLength();
+        }
+
+        [Test]
+        public override void TestNumericField()
+        {
+            base.TestNumericField();
+        }
+
+        [Test]
+        public override void TestIndexedBit()
+        {
+            base.TestIndexedBit();
+        }
+
+        [Test]
+        public override void TestReadSkip()
+        {
+            base.TestReadSkip();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestEmptyDocs()
+        {
+            base.TestEmptyDocs();
+        }
+
+        [Test, Timeout(300000)]
+        public override void TestConcurrentReads()
+        {
+            base.TestConcurrentReads();
+        }
+
+        [Test]
+        public override void TestWriteReadMerge()
+        {
+            base.TestWriteReadMerge();
+        }
+
+        [Test, Timeout(120000)]
+        public override void TestBigDocuments()
+        {
+            base.TestBigDocuments();
+        }
+
+        [Test]
+        public override void TestBulkMergeWithDeletes()
+        {
+            base.TestBulkMergeWithDeletes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a209d718/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs b/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
index 7f4438b..598f373 100644
--- a/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
+++ b/src/Lucene.Net.Tests/core/Codecs/Lucene42/TestLucene42DocValuesFormat.cs
@@ -51,5 +51,531 @@ namespace Lucene.Net.Codecs.Lucene42
         {
             return false;
         }
+
+
+        #region BaseCompressingDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestUniqueValuesCompression()
+        {
+            base.TestUniqueValuesCompression();
+        }
+
+        [Test]
+        public override void TestDateCompression()
+        {
+            base.TestDateCompression();
+        }
+
+        [Test]
+        public override void TestSingleBigValueCompression()
+        {
+            base.TestSingleBigValueCompression();
+        }
+
+        #endregion
+
+        #region BaseDocValuesFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestOneNumber()
+        {
+            base.TestOneNumber();
+        }
+
+        [Test]
+        public override void TestOneFloat()
+        {
+            base.TestOneFloat();
+        }
+
+        [Test]
+        public override void TestTwoNumbers()
+        {
+            base.TestTwoNumbers();
+        }
+
+        [Test]
+        public override void TestTwoBinaryValues()
+        {
+            base.TestTwoBinaryValues();
+        }
+
+        [Test]
+        public override void TestTwoFieldsMixed()
+        {
+            base.TestTwoFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed()
+        {
+            base.TestThreeFieldsMixed();
+        }
+
+        [Test]
+        public override void TestThreeFieldsMixed2()
+        {
+            base.TestThreeFieldsMixed2();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsNumeric()
+        {
+            base.TestTwoDocumentsNumeric();
+        }
+
+        [Test]
+        public override void TestTwoDocumentsMerged()
+        {
+            base.TestTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestBigNumericRange()
+        {
+            base.TestBigNumericRange();
+        }
+
+        [Test]
+        public override void TestBigNumericRange2()
+        {
+            base.TestBigNumericRange2();
+        }
+
+        [Test]
+        public override void TestBytes()
+        {
+            base.TestBytes();
+        }
+
+        [Test]
+        public override void TestBytesTwoDocumentsMerged()
+        {
+            base.TestBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedBytes()
+        {
+            base.TestSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocuments()
+        {
+            base.TestSortedBytesTwoDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesThreeDocuments()
+        {
+            base.TestSortedBytesThreeDocuments();
+        }
+
+        [Test]
+        public override void TestSortedBytesTwoDocumentsMerged()
+        {
+            base.TestSortedBytesTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedMergeAwayAllValues()
+        {
+            base.TestSortedMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestBytesWithNewline()
+        {
+            base.TestBytesWithNewline();
+        }
+
+        [Test]
+        public override void TestMissingSortedBytes()
+        {
+            base.TestMissingSortedBytes();
+        }
+
+        [Test]
+        public override void TestSortedTermsEnum()
+        {
+            base.TestSortedTermsEnum();
+        }
+
+        [Test]
+        public override void TestEmptySortedBytes()
+        {
+            base.TestEmptySortedBytes();
+        }
+
+        [Test]
+        public override void TestEmptyBytes()
+        {
+            base.TestEmptyBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalBytes()
+        {
+            base.TestVeryLargeButLegalBytes();
+        }
+
+        [Test]
+        public override void TestVeryLargeButLegalSortedBytes()
+        {
+            base.TestVeryLargeButLegalSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytes()
+        {
+            base.TestCodecUsesOwnBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytes()
+        {
+            base.TestCodecUsesOwnSortedBytes();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnBytesEachTime()
+        {
+            base.TestCodecUsesOwnBytesEachTime();
+        }
+
+        [Test]
+        public override void TestCodecUsesOwnSortedBytesEachTime()
+        {
+            base.TestCodecUsesOwnSortedBytesEachTime();
+        }
+
+        /*
+         * Simple test case to show how to use the API
+         */
+        [Test]
+        public override void TestDocValuesSimple()
+        {
+            base.TestDocValuesSimple();
+        }
+
+        [Test]
+        public override void TestRandomSortedBytes()
+        {
+            base.TestRandomSortedBytes();
+        }
+
+        [Test]
+        public override void TestBooleanNumericsVsStoredFields()
+        {
+            base.TestBooleanNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteNumericsVsStoredFields()
+        {
+            base.TestByteNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestByteMissingVsFieldCache()
+        {
+            base.TestByteMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestShortNumericsVsStoredFields()
+        {
+            base.TestShortNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestShortMissingVsFieldCache()
+        {
+            base.TestShortMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestIntNumericsVsStoredFields()
+        {
+            base.TestIntNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestIntMissingVsFieldCache()
+        {
+            base.TestIntMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestLongNumericsVsStoredFields()
+        {
+            base.TestLongNumericsVsStoredFields();
+        }
+
+        [Test]
+        public override void TestLongMissingVsFieldCache()
+        {
+            base.TestLongMissingVsFieldCache();
+        }
+
+        [Test]
+        public override void TestBinaryFixedLengthVsStoredFields()
+        {
+            base.TestBinaryFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestBinaryVariableLengthVsStoredFields()
+        {
+            base.TestBinaryVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsStoredFields()
+        {
+            base.TestSortedFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedFixedLengthVsFieldCache()
+        {
+            base.TestSortedFixedLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsFieldCache()
+        {
+            base.TestSortedVariableLengthVsFieldCache();
+        }
+
+        [Test]
+        public override void TestSortedVariableLengthVsStoredFields()
+        {
+            base.TestSortedVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetOneValue()
+        {
+            base.TestSortedSetOneValue();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoFields()
+        {
+            base.TestSortedSetTwoFields();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsMerged()
+        {
+            base.TestSortedSetTwoDocumentsMerged();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValues()
+        {
+            base.TestSortedSetTwoValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoValuesUnordered()
+        {
+            base.TestSortedSetTwoValuesUnordered();
+        }
+
+        [Test]
+        public override void TestSortedSetThreeValuesTwoDocs()
+        {
+            base.TestSortedSetThreeValuesTwoDocs();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissing()
+        {
+            base.TestSortedSetTwoDocumentsLastMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsLastMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsLastMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissing()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissing();
+        }
+
+        [Test]
+        public override void TestSortedSetTwoDocumentsFirstMissingMerge()
+        {
+            base.TestSortedSetTwoDocumentsFirstMissingMerge();
+        }
+
+        [Test]
+        public override void TestSortedSetMergeAwayAllValues()
+        {
+            base.TestSortedSetMergeAwayAllValues();
+        }
+
+        [Test]
+        public override void TestSortedSetTermsEnum()
+        {
+            base.TestSortedSetTermsEnum();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetFixedLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthSingleValuedVsStoredFields()
+        {
+            base.TestSortedSetVariableLengthSingleValuedVsStoredFields();
+        }
+
+        [Test]
+        public override void TestSortedSetFixedLengthVsUninvertedField()
+        {
+            base.TestSortedSetFixedLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestSortedSetVariableLengthVsUninvertedField()
+        {
+            base.TestSortedSetVariableLengthVsUninvertedField();
+        }
+
+        [Test]
+        public override void TestGCDCompression()
+        {
+            base.TestGCDCompression();
+        }
+
+        [Test]
+        public override void TestZeros()
+        {
+            base.TestZeros();
+        }
+
+        [Test]
+        public override void TestZeroOrMin()
+        {
+            base.TestZeroOrMin();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissing()
+        {
+            base.TestTwoNumbersOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoNumbersOneMissingWithMerging()
+        {
+            base.TestTwoNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeNumbersOneMissingWithMerging()
+        {
+            base.TestThreeNumbersOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissing()
+        {
+            base.TestTwoBytesOneMissing();
+        }
+
+        [Test]
+        public override void TestTwoBytesOneMissingWithMerging()
+        {
+            base.TestTwoBytesOneMissingWithMerging();
+        }
+
+        [Test]
+        public override void TestThreeBytesOneMissingWithMerging()
+        {
+            base.TestThreeBytesOneMissingWithMerging();
+        }
+
+        // LUCENE-4853
+        [Test]
+        public override void TestHugeBinaryValues()
+        {
+            base.TestHugeBinaryValues();
+        }
+
+        // TODO: get this out of here and into the deprecated codecs (4.0, 4.2)
+        [Test]
+        public override void TestHugeBinaryValueLimit()
+        {
+            base.TestHugeBinaryValueLimit();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (binary/numeric/sorted, no missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads()
+        {
+            base.TestThreads();
+        }
+
+        /// <summary>
+        /// Tests dv against stored fields with threads (all types + missing)
+        /// </summary>
+        [Test]
+        public override void TestThreads2()
+        {
+            base.TestThreads2();
+        }
+
+        // LUCENE-5218
+        [Test]
+        public override void TestEmptyBinaryValueOnPageSizes()
+        {
+            base.TestEmptyBinaryValueOnPageSizes();
+        }
+
+        #endregion
+
+        #region BaseIndexFileFormatTestCase
+        // LUCENENET NOTE: Tests in an abstract base class are not pulled into the correct
+        // context in Visual Studio. This fixes that with the minimum amount of code necessary
+        // to run them in the correct context without duplicating all of the tests.
+
+        [Test]
+        public override void TestMergeStability()
+        {
+            base.TestMergeStability();
+        }
+
+        #endregion
     }
 }
\ No newline at end of file


[46/58] [abbrv] lucenenet git commit: Fixed several string comparison bugs in Grouping tests

Posted by ni...@apache.org.
Fixed several string comparison bugs in Grouping tests


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

Branch: refs/heads/grouping
Commit: 840c67b6562a29979ed4b5572ebaac1a4dd392b8
Parents: 7c01e88
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 20:29:33 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:57 2016 +0700

----------------------------------------------------------------------
 .../AbstractGroupingTestCase.cs                   |  2 +-
 .../AllGroupHeadsCollectorTest.cs                 | 14 +++++++-------
 .../AllGroupsCollectorTest.cs                     |  2 +-
 .../DistinctValuesCollectorTest.cs                |  4 ++--
 .../GroupFacetCollectorTest.cs                    | 16 ++++++++--------
 .../GroupingSearchTest.cs                         |  2 +-
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs     | 18 +++++++++---------
 7 files changed, 29 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
index 4cc29e3..d4cd062 100644
--- a/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
+++ b/src/Lucene.Net.Tests.Grouping/AbstractGroupingTestCase.cs
@@ -23,7 +23,7 @@ namespace Lucene.Net.Search.Grouping
                 // groups.
                 randomValue = TestUtil.RandomRealisticUnicodeString(Random());
                 //randomValue = TestUtil.randomSimpleString(random());
-            } while ("".equals(randomValue));
+            } while ("".Equals(randomValue, StringComparison.Ordinal));
             return randomValue;
         }
     }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index 80ed421..6b7c06a 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -37,7 +37,7 @@ namespace Lucene.Net.Search.Grouping
             dir,
             NewIndexWriterConfig(TEST_VERSION_CURRENT,
                 new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
-            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseIDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
 
             // 0
@@ -171,7 +171,7 @@ namespace Lucene.Net.Search.Grouping
                         // B/c of DV based impl we can't see the difference between an empty string and a null value.
                         // For that reason we don't generate empty string groups.
                         randomValue = TestUtil.RandomRealisticUnicodeString(Random());
-                    } while ("".equals(randomValue));
+                    } while ("".Equals(randomValue, StringComparison.Ordinal));
                     groups.Add(new BytesRef(randomValue));
                 }
                 string[] contentStrings = new string[TestUtil.NextInt(Random(), 2, 20)];
@@ -201,7 +201,7 @@ namespace Lucene.Net.Search.Grouping
                     dir,
                     NewIndexWriterConfig(TEST_VERSION_CURRENT,
                         new MockAnalyzer(Random())));
-                bool preFlex = "Lucene3x".equals(w.w.Config.Codec.Name);
+                bool preFlex = "Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
                 bool canUseIDV = !preFlex;
                 DocValuesType_e valueType = vts[Random().nextInt(vts.Length)];
 
@@ -467,7 +467,7 @@ namespace Lucene.Net.Search.Grouping
             IDictionary<BytesRef, List<GroupDoc>> groupHeads = new HashMap<BytesRef, List<GroupDoc>>();
             foreach (GroupDoc groupDoc in groupDocs)
             {
-                if (!groupDoc.content.StartsWith(searchTerm))
+                if (!groupDoc.content.StartsWith(searchTerm, StringComparison.Ordinal))
                 {
                     continue;
                 }
@@ -568,15 +568,15 @@ namespace Lucene.Net.Search.Grouping
                             cmp = sortByScoreOnly ? fieldIdToDocID[d1.id] - fieldIdToDocID[d2.id] : 0;
                         }
                     }
-                    else if (sf.Field.equals("sort1"))
+                    else if (sf.Field.Equals("sort1", StringComparison.Ordinal))
                     {
                         cmp = d1.sort1.CompareTo(d2.sort1);
                     }
-                    else if (sf.Field.equals("sort2"))
+                    else if (sf.Field.Equals("sort2", StringComparison.Ordinal))
                     {
                         cmp = d1.sort2.CompareTo(d2.sort2);
                     }
-                    else if (sf.Field.equals("sort3"))
+                    else if (sf.Field.Equals("sort3", StringComparison.Ordinal))
                     {
                         cmp = d1.sort3.CompareTo(d2.sort3);
                     }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
index 32bdbc1..681c644 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupsCollectorTest.cs
@@ -34,7 +34,7 @@ namespace Lucene.Net.Search.Grouping
                 dir,
                 NewIndexWriterConfig(TEST_VERSION_CURRENT,
                     new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
-            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseIDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
 
             // 0
             Document doc = new Document();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
index 58fae2c..24beb86 100644
--- a/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/DistinctValuesCollectorTest.cs
@@ -71,7 +71,7 @@ namespace Lucene.Net.Search.Grouping
                 dir,
                 NewIndexWriterConfig(TEST_VERSION_CURRENT,
                     new MockAnalyzer(random)).SetMergePolicy(NewLogMergePolicy()));
-            bool canUseDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             FieldInfo.DocValuesType_e? dvType = canUseDV ? dvTypes[random.nextInt(dvTypes.Length)] : (FieldInfo.DocValuesType_e?)null;
 
             Document doc = new Document();
@@ -522,7 +522,7 @@ namespace Lucene.Net.Search.Grouping
                 new MockAnalyzer(random)).SetMergePolicy(NewLogMergePolicy())
               );
 
-            bool canUseDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             FieldInfo.DocValuesType_e? dvType = canUseDV ? dvTypes[random.nextInt(dvTypes.Length)] : (FieldInfo.DocValuesType_e?)null;
 
             int numDocs = 86 + random.nextInt(1087) * RANDOM_MULTIPLIER;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
index 8a01ee0..a8f191d 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupFacetCollectorTest.cs
@@ -29,7 +29,7 @@ namespace Lucene.Net.Search.Grouping
                 dir,
                 NewIndexWriterConfig(TEST_VERSION_CURRENT,
                     new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
-            bool canUseDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             bool useDv = canUseDV && Random().nextBoolean();
 
             // 0
@@ -542,7 +542,7 @@ namespace Lucene.Net.Search.Grouping
                     new MockAnalyzer(random)
                 )
             );
-            bool canUseDV = !"Lucene3x".equals(writer.w.Config.Codec.Name);
+            bool canUseDV = !"Lucene3x".Equals(writer.w.Config.Codec.Name, StringComparison.Ordinal);
             bool useDv = canUseDV && !multipleFacetValuesPerDocument && random.nextBoolean();
 
             Document doc = new Document();
@@ -647,8 +647,8 @@ namespace Lucene.Net.Search.Grouping
                 {
                     if (useDv)
                     {
-                        String facetValue = facetValues[random.nextInt(facetValues.size())];
-                        uniqueFacetValues.add(facetValue);
+                        string facetValue = facetValues[random.nextInt(facetValues.size())];
+                        uniqueFacetValues.Add(facetValue);
                         if (!facetToGroups.ContainsKey(facetValue))
                         {
                             facetToGroups[facetValue] = new HashSet<string>();
@@ -668,7 +668,7 @@ namespace Lucene.Net.Search.Grouping
                         foreach (Field facetField in facetFields)
                         {
                             string facetValue = facetValues[random.nextInt(facetValues.size())];
-                            uniqueFacetValues.add(facetValue);
+                            uniqueFacetValues.Add(facetValue);
                             if (!facetToGroups.ContainsKey(facetValue))
                             {
                                 facetToGroups[facetValue] = new HashSet<string>();
@@ -686,7 +686,7 @@ namespace Lucene.Net.Search.Grouping
                 }
                 else
                 {
-                    uniqueFacetValues.add(null);
+                    uniqueFacetValues.Add(null);
                     if (!facetToGroups.ContainsKey(null))
                     {
                         facetToGroups.Put(null, new HashSet<string>());
@@ -783,7 +783,7 @@ namespace Lucene.Net.Search.Grouping
                 facetValues = new HashSet<string>();
                 foreach (string facetValue in context.facetValues)
                 {
-                    if (facetValue != null && facetValue.StartsWith(facetPrefix))
+                    if (facetValue != null && facetValue.StartsWith(facetPrefix, StringComparison.Ordinal))
                     {
                         facetValues.add(facetValue);
                     }
@@ -865,7 +865,7 @@ namespace Lucene.Net.Search.Grouping
         {
             BytesRef facetPrefixBR = facetPrefix == null ? null : new BytesRef(facetPrefix);
             // DocValues cannot be multi-valued:
-            Debug.Assert(!multipleFacetsPerDocument || !groupField.EndsWith("_dv"));
+            Debug.Assert(!multipleFacetsPerDocument || !groupField.EndsWith("_dv", StringComparison.Ordinal));
             return TermGroupFacetCollector.CreateTermGroupFacetCollector(groupField, facetField, multipleFacetsPerDocument, facetPrefixBR, Random().nextInt(1024));
         }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
index 0b80e2e..2971a52 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
@@ -31,7 +31,7 @@ namespace Lucene.Net.Search.Grouping
                 dir,
                 NewIndexWriterConfig(TEST_VERSION_CURRENT,
                     new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
-            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseIDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             List<Document> documents = new List<Document>();
             // 0
             Document doc = new Document();

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/840c67b6/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index 8a45bd5..2291a74 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -41,7 +41,7 @@ namespace Lucene.Net.Search.Grouping
                                        dir,
                                        NewIndexWriterConfig(TEST_VERSION_CURRENT,
                                                             new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
-            bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
+            bool canUseIDV = !"Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
             // 0
             Document doc = new Document();
             AddGroupField(doc, groupField, "author1", canUseIDV);
@@ -448,11 +448,11 @@ namespace Lucene.Net.Search.Grouping
                             cmp = 0;
                         }
                     }
-                    else if (sf.Field.equals("sort1"))
+                    else if (sf.Field.Equals("sort1", StringComparison.Ordinal))
                     {
                         cmp = d1.sort1.CompareTo(d2.sort1);
                     }
-                    else if (sf.Field.equals("sort2"))
+                    else if (sf.Field.Equals("sort2", StringComparison.Ordinal))
                     {
                         cmp = d1.sort2.CompareTo(d2.sort2);
                     }
@@ -539,11 +539,11 @@ namespace Lucene.Net.Search.Grouping
                 {
                     c = new float?(d.score);
                 }
-                else if (sf.Field.equals("sort1"))
+                else if (sf.Field.Equals("sort1", StringComparison.Ordinal))
                 {
                     c = d.sort1;
                 }
-                else if (sf.Field.equals("sort2"))
+                else if (sf.Field.Equals("sort2", StringComparison.Ordinal))
                 {
                     c = d.sort2;
                 }
@@ -597,7 +597,7 @@ namespace Lucene.Net.Search.Grouping
             foreach (GroupDoc d in groupDocs)
             {
                 // TODO: would be better to filter by searchTerm before sorting!
-                if (!d.content.StartsWith(searchTerm))
+                if (!d.content.StartsWith(searchTerm, StringComparison.Ordinal))
                 {
                     continue;
                 }
@@ -823,7 +823,7 @@ namespace Lucene.Net.Search.Grouping
                         // groups.
                         randomValue = TestUtil.RandomRealisticUnicodeString(Random());
                         //randomValue = TestUtil.RandomSimpleString(Random());
-                    } while ("".equals(randomValue));
+                    } while ("".Equals(randomValue, StringComparison.Ordinal));
 
                     groups.Add(new BytesRef(randomValue));
                 }
@@ -854,7 +854,7 @@ namespace Lucene.Net.Search.Grouping
                                                             dir,
                                                             NewIndexWriterConfig(TEST_VERSION_CURRENT,
                                                                                  new MockAnalyzer(Random())));
-                bool preFlex = "Lucene3x".equals(w.w.Config.Codec.Name);
+                bool preFlex = "Lucene3x".Equals(w.w.Config.Codec.Name, StringComparison.Ordinal);
                 bool canUseIDV = !preFlex;
 
                 Document doc = new Document();
@@ -1329,7 +1329,7 @@ namespace Lucene.Net.Search.Grouping
                             }
                         }
 
-                        AssertEquals(docIDToID, expectedGroups, groupsResult, true, true, true, getScores, groupField.EndsWith("_dv"));
+                        AssertEquals(docIDToID, expectedGroups, groupsResult, true, true, true, getScores, groupField.EndsWith("_dv", StringComparison.Ordinal));
 
                         // Confirm merged shards match:
                         AssertEquals(docIDToID, expectedGroups, topGroupsShards, true, false, fillFields, getScores, idvBasedImplsUsedSharded.value);


[44/58] [abbrv] lucenenet git commit: Ported Grouping.TestGrouping

Posted by ni...@apache.org.
Ported Grouping.TestGrouping


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

Branch: refs/heads/grouping
Commit: 4b914b7231fd7e4029fea2108405f3c5d09df398
Parents: 44c29eb
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 6 01:20:40 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:57 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Grouping/SearchGroup.cs          |  27 +-
 src/Lucene.Net.Grouping/TopGroups.cs            |   4 +-
 .../AllGroupHeadsCollectorTest.cs               |  10 +-
 .../Lucene.Net.Tests.Grouping.csproj            |   1 +
 src/Lucene.Net.Tests.Grouping/TestGrouping.cs   | 341 +++++++++++--------
 5 files changed, 215 insertions(+), 168 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/4b914b72/src/Lucene.Net.Grouping/SearchGroup.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/SearchGroup.cs b/src/Lucene.Net.Grouping/SearchGroup.cs
index 693e513..126e974 100644
--- a/src/Lucene.Net.Grouping/SearchGroup.cs
+++ b/src/Lucene.Net.Grouping/SearchGroup.cs
@@ -1,11 +1,8 @@
-\ufeffusing Lucene.Net.Search;
-using Lucene.Net.Support;
+\ufeffusing Lucene.Net.Support;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Lucene.Net.Search.Grouping
 {
@@ -60,20 +57,20 @@ namespace Lucene.Net.Search.Grouping
 
         private class ShardIter<T>
         {
-            public readonly IEnumerator<SearchGroup<T>> iter;
+            public readonly IEnumerator<ISearchGroup<T>> iter;
             public readonly int shardIndex;
 
-            public ShardIter(ICollection<SearchGroup<T>> shard, int shardIndex)
+            public ShardIter(IEnumerable<ISearchGroup<T>> shard, int shardIndex)
             {
                 this.shardIndex = shardIndex;
                 iter = shard.GetEnumerator();
-                //Debug.Assert(iter.hasNext());
+                //Debug.Assert(iter.hasNext()); // No reasonable way to do this in .NET
             }
 
-            public SearchGroup<T> Next()
+            public ISearchGroup<T> Next()
             {
-                Debug.Assert(iter.MoveNext());
-                SearchGroup<T> group = iter.Current;
+                //Debug.Assert(iter.hasNext()); // No reasonable way to do this in .NET
+                ISearchGroup<T> group = iter.Current;
                 if (group.SortValues == null)
                 {
                     throw new ArgumentException("group.sortValues is null; you must pass fillFields=true to the first pass collector");
@@ -216,14 +213,14 @@ namespace Lucene.Net.Search.Grouping
             {
                 groupComp = new GroupComparator<T>(groupSort);
                 queue = new SortedSet<MergedGroup<T>>(groupComp);
-                groupsSeen = new Dictionary<T, MergedGroup<T>>();
+                groupsSeen = new HashMap<T, MergedGroup<T>>();
             }
 
             private void UpdateNextGroup(int topN, ShardIter<T> shard)
             {
                 while (shard.iter.MoveNext())
                 {
-                    SearchGroup<T> group = shard.Next();
+                    ISearchGroup<T> group = shard.Next();
                     MergedGroup<T> mergedGroup = groupsSeen.ContainsKey(group.GroupValue) ? groupsSeen[group.GroupValue] : null;
                     bool isNew = mergedGroup == null;
                     //System.out.println("    next group=" + (group.groupValue == null ? "null" : ((BytesRef) group.groupValue).utf8ToString()) + " sort=" + Arrays.toString(group.sortValues));
@@ -304,7 +301,7 @@ namespace Lucene.Net.Search.Grouping
                 }
             }
 
-            public ICollection<SearchGroup<T>> Merge(IList<ICollection<SearchGroup<T>>> shards, int offset, int topN)
+            public ICollection<SearchGroup<T>> Merge(IList<IEnumerable<ISearchGroup<T>>> shards, int offset, int topN)
             {
 
                 int maxQueueSize = offset + topN;
@@ -313,7 +310,7 @@ namespace Lucene.Net.Search.Grouping
                 // Init queue:
                 for (int shardIDX = 0; shardIDX < shards.Count; shardIDX++)
                 {
-                    ICollection<SearchGroup<T>> shard = shards[shardIDX];
+                    IEnumerable<ISearchGroup<T>> shard = shards[shardIDX];
                     if (shard.Any())
                     {
                         //System.out.println("  insert shard=" + shardIDX);
@@ -373,7 +370,7 @@ namespace Lucene.Net.Search.Grouping
          *
          * <p>NOTE: this returns null if the topGroups is empty.
          */
-        public static ICollection<SearchGroup<T>> Merge<T>(IList<ICollection<SearchGroup<T>>> topGroups, int offset, int topN, Sort groupSort)
+        public static ICollection<SearchGroup<T>> Merge<T>(IList<IEnumerable<ISearchGroup<T>>> topGroups, int offset, int topN, Sort groupSort)
         {
             if (topGroups.Count == 0)
             {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/4b914b72/src/Lucene.Net.Grouping/TopGroups.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Grouping/TopGroups.cs b/src/Lucene.Net.Grouping/TopGroups.cs
index b5d5c65..54a9547 100644
--- a/src/Lucene.Net.Grouping/TopGroups.cs
+++ b/src/Lucene.Net.Grouping/TopGroups.cs
@@ -115,7 +115,7 @@ namespace Lucene.Net.Search.Grouping
         /// <b>NOTE</b>: the topDocs in each GroupDocs is actually
         /// an instance of TopDocsAndShards
         /// </summary>
-        public static TopGroups<T> Merge<T>(TopGroups<T>[] shardGroups, Sort groupSort, Sort docSort, int docOffset, int docTopN, ScoreMergeMode scoreMergeMode)
+        public static TopGroups<T> Merge<T>(ITopGroups<T>[] shardGroups, Sort groupSort, Sort docSort, int docOffset, int docTopN, ScoreMergeMode scoreMergeMode)
         {
             //System.out.println("TopGroups.merge");
 
@@ -164,7 +164,7 @@ namespace Lucene.Net.Search.Grouping
                 for (int shardIdx = 0; shardIdx < shardGroups.Length; shardIdx++)
                 {
                     //System.out.println("    shard=" + shardIDX);
-                    TopGroups<T> shard = shardGroups[shardIdx];
+                    ITopGroups<T> shard = shardGroups[shardIdx];
                     var shardGroupDocs = shard.Groups[groupIDX];
                     if (groupValue == null)
                     {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/4b914b72/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
index 2a0b307..80ed421 100644
--- a/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/AllGroupHeadsCollectorTest.cs
@@ -220,8 +220,9 @@ namespace Lucene.Net.Search.Grouping
                         case DocValuesType_e.SORTED:
                             valuesField = new SortedDocValuesField("group_dv", new BytesRef());
                             break;
-                            //default:
-                            //    fail("unhandled type");
+                        default:
+                            fail("unhandled type");
+                            break;
                     }
                     doc.Add(valuesField);
                 }
@@ -685,8 +686,9 @@ namespace Lucene.Net.Search.Grouping
                     case DocValuesType_e.SORTED:
                         valuesField = new SortedDocValuesField(groupField + "_dv", new BytesRef(value));
                         break;
-                        //default:
-                        //    fail("unhandled type");
+                    default:
+                        fail("unhandled type");
+                        break;
                 }
                 doc.Add(valuesField);
             }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/4b914b72/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
index f5906f1..0141a9a 100644
--- a/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
+++ b/src/Lucene.Net.Tests.Grouping/Lucene.Net.Tests.Grouping.csproj
@@ -51,6 +51,7 @@
     <Compile Include="GroupFacetCollectorTest.cs" />
     <Compile Include="GroupingSearchTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestGrouping.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/4b914b72/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
index cda472d..8a45bd5 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGrouping.cs
@@ -11,6 +11,7 @@ using Lucene.Net.Util;
 using Lucene.Net.Util.Mutable;
 using NUnit.Framework;
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -26,7 +27,7 @@ namespace Lucene.Net.Search.Grouping
     public class TestGrouping : LuceneTestCase
     {
         [Test]
-        public void testBasic()
+        public virtual void TestBasic()
         {
 
             string groupField = "author";
@@ -43,42 +44,42 @@ namespace Lucene.Net.Search.Grouping
             bool canUseIDV = !"Lucene3x".equals(w.w.Config.Codec.Name);
             // 0
             Document doc = new Document();
-            addGroupField(doc, groupField, "author1", canUseIDV);
+            AddGroupField(doc, groupField, "author1", canUseIDV);
             doc.Add(new TextField("content", "random text", Field.Store.YES));
             doc.Add(new Field("id", "1", customType));
             w.AddDocument(doc);
 
             // 1
             doc = new Document();
-            addGroupField(doc, groupField, "author1", canUseIDV);
+            AddGroupField(doc, groupField, "author1", canUseIDV);
             doc.Add(new TextField("content", "some more random text", Field.Store.YES));
             doc.Add(new Field("id", "2", customType));
             w.AddDocument(doc);
 
             // 2
             doc = new Document();
-            addGroupField(doc, groupField, "author1", canUseIDV);
+            AddGroupField(doc, groupField, "author1", canUseIDV);
             doc.Add(new TextField("content", "some more random textual data", Field.Store.YES));
             doc.Add(new Field("id", "3", customType));
             w.AddDocument(doc);
 
             // 3
             doc = new Document();
-            addGroupField(doc, groupField, "author2", canUseIDV);
+            AddGroupField(doc, groupField, "author2", canUseIDV);
             doc.Add(new TextField("content", "some random text", Field.Store.YES));
             doc.Add(new Field("id", "4", customType));
             w.AddDocument(doc);
 
             // 4
             doc = new Document();
-            addGroupField(doc, groupField, "author3", canUseIDV);
+            AddGroupField(doc, groupField, "author3", canUseIDV);
             doc.Add(new TextField("content", "some more random text", Field.Store.YES));
             doc.Add(new Field("id", "5", customType));
             w.AddDocument(doc);
 
             // 5
             doc = new Document();
-            addGroupField(doc, groupField, "author3", canUseIDV);
+            AddGroupField(doc, groupField, "author3", canUseIDV);
             doc.Add(new TextField("content", "random", Field.Store.YES));
             doc.Add(new Field("id", "6", customType));
             w.AddDocument(doc);
@@ -99,54 +100,58 @@ namespace Lucene.Net.Search.Grouping
                 groupField += "_dv";
             }
 
-            AbstractFirstPassGroupingCollector <?> c1 = createRandomFirstPassCollector(groupField, groupSort, 10);
-            indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c1);
+            IAbstractFirstPassGroupingCollector<IComparable> c1 = CreateRandomFirstPassCollector(groupField, groupSort, 10);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c1 as Collector);
 
-            AbstractSecondPassGroupingCollector <?> c2 = createSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, true, true);
-            indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c2);
+            IAbstractSecondPassGroupingCollector<IComparable> c2 = CreateSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, true, true);
+            // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+            // so this cast is not necessary. Consider eliminating the Collector abstract class.
+            indexSearcher.Search(new TermQuery(new Index.Term("content", "random")), c2 as Collector);
 
-            TopGroups <?> groups = c2.getTopGroups(0);
-            assertFalse(float.IsNaN(groups.maxScore));
+            ITopGroups<IComparable> groups = c2.GetTopGroups(0);
+            assertFalse(float.IsNaN(groups.MaxScore));
 
-            assertEquals(7, groups.totalHitCount);
-            assertEquals(7, groups.totalGroupedHitCount);
-            assertEquals(4, groups.groups.Length);
+            assertEquals(7, groups.TotalHitCount);
+            assertEquals(7, groups.TotalGroupedHitCount);
+            assertEquals(4, groups.Groups.Length);
 
             // relevance order: 5, 0, 3, 4, 1, 2, 6
 
             // the later a document is added the higher this docId
             // value
-            GroupDocs <?> group = groups.groups[0];
-            compareGroupValue("author3", group);
-            assertEquals(2, group.scoreDocs.Length);
-            assertEquals(5, group.scoreDocs[0].doc);
-            assertEquals(4, group.scoreDocs[1].doc);
-            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
-
-            group = groups.groups[1];
-            compareGroupValue("author1", group);
-            assertEquals(3, group.scoreDocs.Length);
-            assertEquals(0, group.scoreDocs[0].doc);
-            assertEquals(1, group.scoreDocs[1].doc);
-            assertEquals(2, group.scoreDocs[2].doc);
-            assertTrue(group.scoreDocs[0].score > group.scoreDocs[1].score);
-            assertTrue(group.scoreDocs[1].score > group.scoreDocs[2].score);
-
-            group = groups.groups[2];
-            compareGroupValue("author2", group);
-            assertEquals(1, group.scoreDocs.Length);
-            assertEquals(3, group.scoreDocs[0].doc);
-
-            group = groups.groups[3];
-            compareGroupValue(null, group);
-            assertEquals(1, group.scoreDocs.Length);
-            assertEquals(6, group.scoreDocs[0].doc);
+            IGroupDocs<IComparable> group = groups.Groups[0];
+            CompareGroupValue("author3", group);
+            assertEquals(2, group.ScoreDocs.Length);
+            assertEquals(5, group.ScoreDocs[0].Doc);
+            assertEquals(4, group.ScoreDocs[1].Doc);
+            assertTrue(group.ScoreDocs[0].Score > group.ScoreDocs[1].Score);
+
+            group = groups.Groups[1];
+            CompareGroupValue("author1", group);
+            assertEquals(3, group.ScoreDocs.Length);
+            assertEquals(0, group.ScoreDocs[0].Doc);
+            assertEquals(1, group.ScoreDocs[1].Doc);
+            assertEquals(2, group.ScoreDocs[2].Doc);
+            assertTrue(group.ScoreDocs[0].Score > group.ScoreDocs[1].Score);
+            assertTrue(group.ScoreDocs[1].Score > group.ScoreDocs[2].Score);
+
+            group = groups.Groups[2];
+            CompareGroupValue("author2", group);
+            assertEquals(1, group.ScoreDocs.Length);
+            assertEquals(3, group.ScoreDocs[0].Doc);
+
+            group = groups.Groups[3];
+            CompareGroupValue(null, group);
+            assertEquals(1, group.ScoreDocs.Length);
+            assertEquals(6, group.ScoreDocs[0].Doc);
 
             indexSearcher.IndexReader.Dispose();
             dir.Dispose();
         }
 
-        private void addGroupField(Document doc, string groupField, string value, bool canUseIDV)
+        private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV)
         {
             doc.Add(new TextField(groupField, value, Field.Store.YES));
             if (canUseIDV)
@@ -155,13 +160,13 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private AbstractFirstPassGroupingCollector<?> createRandomFirstPassCollector(String groupField, Sort groupSort, int topDocs)
+        private IAbstractFirstPassGroupingCollector<IComparable> CreateRandomFirstPassCollector(string groupField, Sort groupSort, int topDocs)
         {
-            AbstractFirstPassGroupingCollector <?> selected;
-            if (Random().nextbool())
+            IAbstractFirstPassGroupingCollector<IComparable> selected;
+            if (Random().nextBoolean())
             {
                 ValueSource vs = new BytesRefFieldSource(groupField);
-                selected = new FunctionFirstPassGroupingCollector(vs, new Dictionary(), groupSort, topDocs);
+                selected = new FunctionFirstPassGroupingCollector(vs, new Hashtable(), groupSort, topDocs);
             }
             else
             {
@@ -174,20 +179,22 @@ namespace Lucene.Net.Search.Grouping
             return selected;
         }
 
-        private AbstractFirstPassGroupingCollector<?> createFirstPassCollector(string groupField, Sort groupSort, int topDocs, AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector)
+        private IAbstractFirstPassGroupingCollector<T> CreateFirstPassCollector<T>(string groupField, Sort groupSort, int topDocs, IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector)
         {
             if (typeof(TermFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
             {
                 ValueSource vs = new BytesRefFieldSource(groupField);
-                return new FunctionFirstPassGroupingCollector(vs, new Dictionary(), groupSort, topDocs);
+                return new FunctionFirstPassGroupingCollector(vs, new Hashtable(), groupSort, topDocs)
+                    as IAbstractFirstPassGroupingCollector<T>;
             }
             else
             {
-                return new TermFirstPassGroupingCollector(groupField, groupSort, topDocs);
+                return new TermFirstPassGroupingCollector(groupField, groupSort, topDocs)
+                    as IAbstractFirstPassGroupingCollector<T>;
             }
         }
 
-        private <T> AbstractSecondPassGroupingCollector<T> createSecondPassCollector(AbstractFirstPassGroupingCollector firstPassGroupingCollector,
+        private IAbstractSecondPassGroupingCollector<T> CreateSecondPassCollector<T>(IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
                                                                               string groupField,
                                                                               Sort groupSort,
                                                                               Sort sortWithinGroup,
@@ -200,19 +207,19 @@ namespace Lucene.Net.Search.Grouping
 
             if (typeof(TermFirstPassGroupingCollector).IsAssignableFrom(firstPassGroupingCollector.GetType()))
             {
-                ICollection<SearchGroup<BytesRef>> searchGroups = firstPassGroupingCollector.GetTopGroups(groupOffset, fillSortFields);
-                return (AbstractSecondPassGroupingCollector)new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
+                var searchGroups = firstPassGroupingCollector.GetTopGroups(groupOffset, fillSortFields);
+                return (IAbstractSecondPassGroupingCollector<T>)new TermSecondPassGroupingCollector(groupField, searchGroups as IEnumerable<ISearchGroup<BytesRef>>, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
             }
             else
             {
                 ValueSource vs = new BytesRefFieldSource(groupField);
-                ICollection<SearchGroup<MutableValue>> searchGroups = firstPassGroupingCollector.GetTopGroups(groupOffset, fillSortFields);
-                return (AbstractSecondPassGroupingCollector)new FunctionSecondPassGroupingCollector(searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap());
+                var searchGroups = firstPassGroupingCollector.GetTopGroups(groupOffset, fillSortFields);
+                return (IAbstractSecondPassGroupingCollector<T>)new FunctionSecondPassGroupingCollector(searchGroups as IEnumerable<ISearchGroup<MutableValue>>, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new Hashtable());
             }
         }
 
         // Basically converts searchGroups from MutableValue to BytesRef if grouping by ValueSource
-        private AbstractSecondPassGroupingCollector<?> createSecondPassCollector(AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector,
+        private IAbstractSecondPassGroupingCollector<T> CreateSecondPassCollector<T>(IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
                                                                               string groupField,
                                                                               ICollection<SearchGroup<BytesRef>> searchGroups,
                                                                               Sort groupSort,
@@ -224,7 +231,8 @@ namespace Lucene.Net.Search.Grouping
         {
             if (firstPassGroupingCollector.GetType().IsAssignableFrom(typeof(TermFirstPassGroupingCollector)))
             {
-                return new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
+                return new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields) 
+                    as IAbstractSecondPassGroupingCollector<T>;
             }
             else
             {
@@ -234,39 +242,40 @@ namespace Lucene.Net.Search.Grouping
                 {
                     SearchGroup<MutableValue> sg = new SearchGroup<MutableValue>();
                     MutableValueStr groupValue = new MutableValueStr();
-                    if (mergedTopGroup.groupValue != null)
+                    if (mergedTopGroup.GroupValue != null)
                     {
-                        groupValue.Value = mergedTopGroup.groupValue;
+                        groupValue.Value = mergedTopGroup.GroupValue;
                     }
                     else
                     {
                         groupValue.Value = new BytesRef();
                         groupValue.Exists = false;
                     }
-                    sg.groupValue = groupValue;
-                    sg.sortValues = mergedTopGroup.sortValues;
+                    sg.GroupValue = groupValue;
+                    sg.SortValues = mergedTopGroup.SortValues;
                     mvalSearchGroups.Add(sg);
                 }
 
-                return new FunctionSecondPassGroupingCollector(mvalSearchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap<>());
+                return new FunctionSecondPassGroupingCollector(mvalSearchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new Hashtable())
+                    as IAbstractSecondPassGroupingCollector<T>;
             }
         }
 
-        private AbstractAllGroupsCollector<?> createAllGroupsCollector(AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector,
+        private IAbstractAllGroupsCollector<T> CreateAllGroupsCollector<T>(IAbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
                                                                     string groupField)
         {
             if (firstPassGroupingCollector.GetType().IsAssignableFrom(typeof(TermFirstPassGroupingCollector)))
             {
-                return new TermAllGroupsCollector(groupField);
+                return new TermAllGroupsCollector(groupField) as IAbstractAllGroupsCollector<T>;
             }
             else
             {
                 ValueSource vs = new BytesRefFieldSource(groupField);
-                return new FunctionAllGroupsCollector(vs, new HashMap<>());
+                return new FunctionAllGroupsCollector(vs, new Hashtable()) as IAbstractAllGroupsCollector<T>;
             }
         }
 
-        private void compareGroupValue<T>(string expected, GroupDocs<T> group)
+        private void CompareGroupValue<T>(string expected, IGroupDocs<T> group)
         {
             if (expected == null)
             {
@@ -301,27 +310,28 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private ICollection<SearchGroup<BytesRef>> getSearchGroups<T>(AbstractFirstPassGroupingCollector<T> c, int groupOffset, bool fillFields)
+        private IEnumerable<ISearchGroup<BytesRef>> GetSearchGroups<T>(IAbstractFirstPassGroupingCollector<T> c, int groupOffset, bool fillFields)
         {
             if (typeof(TermFirstPassGroupingCollector).IsAssignableFrom(c.GetType()))
             {
 
-                return (ICollection<SearchGroup<BytesRef>>)c.GetTopGroups(groupOffset, fillFields);
+                return (IEnumerable<ISearchGroup<BytesRef>>)c.GetTopGroups(groupOffset, fillFields);
             }
             else if (typeof(FunctionFirstPassGroupingCollector).IsAssignableFrom(c.GetType()))
             {
-                var mutableValueGroups = c.GetTopGroups(groupOffset, fillFields);
+                // LUCENENET TODO: Can we remove this cast?
+                var mutableValueGroups = c.GetTopGroups(groupOffset, fillFields) as IEnumerable<ISearchGroup<MutableValue>>;
                 if (mutableValueGroups == null)
                 {
                     return null;
                 }
 
-                List<SearchGroup<BytesRef>> groups = new List<SearchGroup<BytesRef>>(mutableValueGroups.size());
+                List<SearchGroup<BytesRef>> groups = new List<SearchGroup<BytesRef>>(mutableValueGroups.Count());
                 foreach (var mutableValueGroup in mutableValueGroups)
                 {
                     SearchGroup<BytesRef> sg = new SearchGroup<BytesRef>();
-                    sg.groupValue = mutableValueGroup.groupValue.Exists ? ((MutableValueStr)mutableValueGroup.groupValue).Value : null;
-                    sg.sortValues = mutableValueGroup.sortValues;
+                    sg.GroupValue = mutableValueGroup.GroupValue.Exists ? ((MutableValueStr)mutableValueGroup.GroupValue).Value : null;
+                    sg.SortValues = mutableValueGroup.SortValues;
                     groups.Add(sg);
                 }
                 return groups;
@@ -330,7 +340,7 @@ namespace Lucene.Net.Search.Grouping
             return null;
         }
 
-        private TopGroups<BytesRef> getTopGroups<T>(AbstractSecondPassGroupingCollector<T> c, int withinGroupOffset)
+        private ITopGroups<BytesRef> GetTopGroups<T>(IAbstractSecondPassGroupingCollector<T> c, int withinGroupOffset)
         {
             if (c.GetType().IsAssignableFrom(typeof(TermSecondPassGroupingCollector)))
             {
@@ -338,7 +348,7 @@ namespace Lucene.Net.Search.Grouping
             }
             else if (c.GetType().IsAssignableFrom(typeof(FunctionSecondPassGroupingCollector)))
             {
-                TopGroups<MutableValue> mvalTopGroups = ((FunctionSecondPassGroupingCollector)c).GetTopGroups(withinGroupOffset);
+                ITopGroups<MutableValue> mvalTopGroups = ((FunctionSecondPassGroupingCollector)c).GetTopGroups(withinGroupOffset);
                 List<GroupDocs<BytesRef>> groups = new List<GroupDocs<BytesRef>>(mvalTopGroups.Groups.Length);
                 foreach (GroupDocs<MutableValue> mvalGd in mvalTopGroups.Groups)
                 {
@@ -353,6 +363,9 @@ namespace Lucene.Net.Search.Grouping
 
         internal class GroupDoc
         {
+            private static int instanceIndex;
+            internal readonly int instanceId;
+
             internal readonly int id;
             internal readonly BytesRef group;
             internal readonly BytesRef sort1;
@@ -364,6 +377,8 @@ namespace Lucene.Net.Search.Grouping
 
             public GroupDoc(int id, BytesRef group, BytesRef sort1, BytesRef sort2, string content)
             {
+                this.instanceId = instanceIndex++;
+
                 this.id = id;
                 this.group = group;
                 this.sort1 = sort1;
@@ -372,7 +387,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private Sort getRandomSort()
+        private Sort GetRandomSort()
         {
             List<SortField> sortFields = new List<SortField>();
             if (Random().nextInt(7) == 2)
@@ -450,14 +465,18 @@ namespace Lucene.Net.Search.Grouping
                     {
                         return sf.Reverse ? -cmp : cmp;
                     }
+                    else
+                    {
+                        // should never get here
+                    }
                 }
                 // Our sort always fully tie breaks:
-                fail();
+                //fail();
                 return 0;
             }
         }
 
-        private IComparer<GroupDoc> getComparator(Sort sort)
+        private IComparer<GroupDoc> GetComparator(Sort sort)
         {
             SortField[] sortFields = sort.GetSort();
             return new ComparerAnonymousHelper(this, sortFields);
@@ -538,7 +557,7 @@ namespace Lucene.Net.Search.Grouping
             return fields;
         }
 
-        private string groupToString(BytesRef b)
+        private string GroupToString(BytesRef b)
         {
             if (b == null)
             {
@@ -550,7 +569,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private TopGroups<BytesRef> slowGrouping(GroupDoc[] groupDocs,
+        private TopGroups<BytesRef> SlowGrouping(GroupDoc[] groupDocs,
                                                  string searchTerm,
                                                  bool fillFields,
                                                  bool getScores,
@@ -564,7 +583,7 @@ namespace Lucene.Net.Search.Grouping
                                                  int docOffset)
         {
 
-            IComparer<GroupDoc> groupSortComp = getComparator(groupSort);
+            IComparer<GroupDoc> groupSortComp = GetComparator(groupSort);
 
             Array.Sort(groupDocs, groupSortComp);
             HashMap<BytesRef, List<GroupDoc>> groups = new HashMap<BytesRef, List<GroupDoc>>();
@@ -617,7 +636,7 @@ namespace Lucene.Net.Search.Grouping
 
             int limit = Math.Min(groupOffset + topNGroups, groups.size());
 
-            IComparer<GroupDoc> docSortComp = getComparator(docSort);
+            IComparer<GroupDoc> docSortComp = GetComparator(docSort);
 
             GroupDocs<BytesRef>[] result = new GroupDocs<BytesRef>[limit - groupOffset];
             int totalGroupedHitCount = 0;
@@ -674,7 +693,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private DirectoryReader getDocBlockReader(Directory dir, GroupDoc[] groupDocs)
+        private DirectoryReader GetDocBlockReader(Directory dir, GroupDoc[] groupDocs)
         {
             // Coalesce by group, but in random order:
             //Collections.shuffle(Arrays.asList(groupDocs), Random());
@@ -772,7 +791,7 @@ namespace Lucene.Net.Search.Grouping
         }
 
         [Test]
-        public void testRandom()
+        public virtual void TestRandom()
         {
             int numberOfRuns = TestUtil.NextInt(Random(), 3, 6);
             for (int iter = 0; iter < numberOfRuns; iter++)
@@ -787,6 +806,7 @@ namespace Lucene.Net.Search.Grouping
 
                 int numGroups = TestUtil.NextInt(Random(), 1, numDocs);
 
+
                 if (VERBOSE)
                 {
                     Console.WriteLine("TEST: numDocs=" + numDocs + " numGroups=" + numGroups);
@@ -802,7 +822,7 @@ namespace Lucene.Net.Search.Grouping
                         // For that reason we don't generate empty string
                         // groups.
                         randomValue = TestUtil.RandomRealisticUnicodeString(Random());
-                        //randomValue = TestUtil.randomSimpleString(Random());
+                        //randomValue = TestUtil.RandomSimpleString(Random());
                     } while ("".equals(randomValue));
 
                     groups.Add(new BytesRef(randomValue));
@@ -963,7 +983,7 @@ namespace Lucene.Net.Search.Grouping
                     // Build 2nd index, where docs are added in blocks by
                     // group, so we can use single pass collector
                     dirBlocks = NewDirectory();
-                    rBlocks = getDocBlockReader(dirBlocks, groupDocs);
+                    rBlocks = GetDocBlockReader(dirBlocks, groupDocs);
                     Filter lastDocInBlock = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Term("groupend", "x"))));
                     FieldCache.Ints docIDToIDBlocks = FieldCache.DEFAULT.GetInts(SlowCompositeReaderWrapper.Wrap(rBlocks), "id", false);
 
@@ -1009,10 +1029,10 @@ namespace Lucene.Net.Search.Grouping
                         bool fillFields = Random().nextBoolean();
                         bool getScores = Random().nextBoolean();
                         bool getMaxScores = Random().nextBoolean();
-                        Sort groupSort = getRandomSort();
-                        //final Sort groupSort = new Sort(new SortField[] {new SortField("sort1", SortField.STRING), new SortField("id", SortField.INT)});
+                        Sort groupSort = GetRandomSort();
+                        //Sort groupSort = new Sort(new SortField[] {new SortField("sort1", SortField.Type_e.STRING), new SortField("id", SortField.Type_e.INT)});
                         // TODO: also test null (= sort by relevance)
-                        Sort docSort = getRandomSort();
+                        Sort docSort = GetRandomSort();
 
                         foreach (SortField sf in docSort.GetSort())
                         {
@@ -1058,14 +1078,14 @@ namespace Lucene.Net.Search.Grouping
                         {
                             Console.WriteLine("  groupField=" + groupField);
                         }
-                        AbstractFirstPassGroupingCollector <?> c1 = createRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
+                        IAbstractFirstPassGroupingCollector<IComparable> c1 = CreateRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
                         CachingCollector cCache;
                         Collector c;
 
-                        AbstractAllGroupsCollector <?> allGroupsCollector;
+                        IAbstractAllGroupsCollector<IComparable> allGroupsCollector;
                         if (doAllGroups)
                         {
-                            allGroupsCollector = createAllGroupsCollector(c1, groupField);
+                            allGroupsCollector = CreateAllGroupsCollector(c1, groupField);
                         }
                         else
                         {
@@ -1086,12 +1106,16 @@ namespace Lucene.Net.Search.Grouping
                             {
                                 if (doAllGroups)
                                 {
-                                    cCache = CachingCollector.Create(c1, true, maxCacheMB);
-                                    c = MultiCollector.Wrap(cCache, allGroupsCollector);
+                                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                    cCache = CachingCollector.Create(c1 as Collector, true, maxCacheMB);
+                                    c = MultiCollector.Wrap(cCache, allGroupsCollector as Collector);
                                 }
                                 else
                                 {
-                                    c = cCache = CachingCollector.Create(c1, true, maxCacheMB);
+                                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                    c = cCache = CachingCollector.Create(c1 as Collector, true, maxCacheMB);
                                 }
                             }
                             else
@@ -1105,11 +1129,15 @@ namespace Lucene.Net.Search.Grouping
                             cCache = null;
                             if (doAllGroups)
                             {
-                                c = MultiCollector.Wrap(c1, allGroupsCollector);
+                                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                c = MultiCollector.Wrap(c1 as Collector, allGroupsCollector as Collector);
                             }
                             else
                             {
-                                c = c1;
+                                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                c = c1 as Collector;
                             }
                         }
 
@@ -1123,27 +1151,35 @@ namespace Lucene.Net.Search.Grouping
                             if (cCache.Cached)
                             {
                                 // Replay for first-pass grouping
-                                cCache.Replay(c1);
+                                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                cCache.Replay(c1 as Collector);
                                 if (doAllGroups)
                                 {
                                     // Replay for all groups:
-                                    cCache.Replay(allGroupsCollector);
+                                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                    cCache.Replay(allGroupsCollector as Collector);
                                 }
                             }
                             else
                             {
                                 // Replay by re-running search:
-                                s.Search(query, c1);
+                                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                s.Search(query, c1 as Collector);
                                 if (doAllGroups)
                                 {
-                                    s.Search(query, allGroupsCollector);
+                                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                    s.Search(query, allGroupsCollector as Collector);
                                 }
                             }
                         }
 
                         // Get 1st pass top groups
-                        ICollection<SearchGroup<BytesRef>> topGroups = getSearchGroups(c1, groupOffset, fillFields);
-                        TopGroups<BytesRef> groupsResult;
+                        IEnumerable<ISearchGroup<BytesRef>> topGroups = GetSearchGroups(c1, groupOffset, fillFields);
+                        ITopGroups<BytesRef> groupsResult;
                         if (VERBOSE)
                         {
                             Console.WriteLine("TEST: first pass topGroups");
@@ -1155,7 +1191,7 @@ namespace Lucene.Net.Search.Grouping
                             {
                                 foreach (SearchGroup<BytesRef> searchGroup in topGroups)
                                 {
-                                    Console.WriteLine("  " + (searchGroup.groupValue == null ? "null" : searchGroup.groupValue.Utf8ToString()) + ": " + Arrays.ToString(searchGroup.sortValues));
+                                    Console.WriteLine("  " + (searchGroup.GroupValue == null ? "null" : searchGroup.GroupValue.Utf8ToString()) + ": " + Arrays.ToString(searchGroup.SortValues));
                                 }
                             }
                         }
@@ -1163,9 +1199,9 @@ namespace Lucene.Net.Search.Grouping
                         // Get 1st pass top groups using shards
 
                         ValueHolder<bool> idvBasedImplsUsedSharded = new ValueHolder<bool>(false);
-                        TopGroups<BytesRef> topGroupsShards = searchShards(s, shards.subSearchers, query, groupSort, docSort,
+                        TopGroups<BytesRef> topGroupsShards = SearchShards(s, shards.subSearchers, query, groupSort, docSort,
                            groupOffset, topNGroups, docOffset, docsPerGroup, getScores, getMaxScores, canUseIDV, preFlex, idvBasedImplsUsedSharded);
-                        AbstractSecondPassGroupingCollector <?> c2;
+                        IAbstractSecondPassGroupingCollector<IComparable> c2;
                         if (topGroups != null)
                         {
 
@@ -1174,11 +1210,11 @@ namespace Lucene.Net.Search.Grouping
                                 Console.WriteLine("TEST: topGroups");
                                 foreach (SearchGroup<BytesRef> searchGroup in topGroups)
                                 {
-                                    Console.WriteLine("  " + (searchGroup.groupValue == null ? "null" : searchGroup.groupValue.Utf8ToString()) + ": " + Arrays.ToString(searchGroup.sortValues));
+                                    Console.WriteLine("  " + (searchGroup.GroupValue == null ? "null" : searchGroup.GroupValue.Utf8ToString()) + ": " + Arrays.ToString(searchGroup.SortValues));
                                 }
                             }
 
-                            c2 = createSecondPassCollector(c1, groupField, groupSort, docSort, groupOffset, docOffset + docsPerGroup, getScores, getMaxScores, fillFields);
+                            c2 = CreateSecondPassCollector(c1, groupField, groupSort, docSort, groupOffset, docOffset + docsPerGroup, getScores, getMaxScores, fillFields);
                             if (doCache)
                             {
                                 if (cCache.Cached)
@@ -1187,7 +1223,9 @@ namespace Lucene.Net.Search.Grouping
                                     {
                                         Console.WriteLine("TEST: cache is intact");
                                     }
-                                    cCache.Replay(c2);
+                                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                    cCache.Replay(c2 as Collector);
                                 }
                                 else
                                 {
@@ -1195,22 +1233,26 @@ namespace Lucene.Net.Search.Grouping
                                     {
                                         Console.WriteLine("TEST: cache was too large");
                                     }
-                                    s.Search(query, c2);
+                                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                    s.Search(query, c2 as Collector);
                                 }
                             }
                             else
                             {
-                                s.Search(query, c2);
+                                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                                s.Search(query, c2 as Collector);
                             }
 
                             if (doAllGroups)
                             {
-                                TopGroups<BytesRef> tempTopGroups = getTopGroups(c2, docOffset);
-                                groupsResult = new TopGroups<BytesRef>(tempTopGroups, allGroupsCollector.getGroupCount());
+                                ITopGroups<BytesRef> tempTopGroups = GetTopGroups(c2, docOffset);
+                                groupsResult = new TopGroups<BytesRef>(tempTopGroups, allGroupsCollector.GroupCount);
                             }
                             else
                             {
-                                groupsResult = getTopGroups(c2, docOffset);
+                                groupsResult = GetTopGroups(c2, docOffset);
                             }
                         }
                         else
@@ -1223,7 +1265,7 @@ namespace Lucene.Net.Search.Grouping
                             }
                         }
 
-                        TopGroups<BytesRef> expectedGroups = slowGrouping(groupDocs, searchTerm, fillFields, getScores, getMaxScores, doAllGroups, groupSort, docSort, topNGroups, docsPerGroup, groupOffset, docOffset);
+                        TopGroups<BytesRef> expectedGroups = SlowGrouping(groupDocs, searchTerm, fillFields, getScores, getMaxScores, doAllGroups, groupSort, docSort, topNGroups, docsPerGroup, groupOffset, docOffset);
 
                         if (VERBOSE)
                         {
@@ -1234,7 +1276,7 @@ namespace Lucene.Net.Search.Grouping
                             else
                             {
                                 Console.WriteLine("TEST: expected groups totalGroupedHitCount=" + expectedGroups.TotalGroupedHitCount);
-                                foreach (GroupDocs<BytesRef> gd in expectedGroups.Groups)
+                                foreach (IGroupDocs<BytesRef> gd in expectedGroups.Groups)
                                 {
                                     Console.WriteLine("  group=" + (gd.GroupValue == null ? "null" : gd.GroupValue.Utf8ToString()) + " totalHits=" + gd.TotalHits + " scoreDocs.len=" + gd.ScoreDocs.Length);
                                     foreach (ScoreDoc sd in gd.ScoreDocs)
@@ -1287,13 +1329,13 @@ namespace Lucene.Net.Search.Grouping
                             }
                         }
 
-                        assertEquals(docIDToID, expectedGroups, groupsResult, true, true, true, getScores, groupField.EndsWith("_dv"));
+                        AssertEquals(docIDToID, expectedGroups, groupsResult, true, true, true, getScores, groupField.EndsWith("_dv"));
 
                         // Confirm merged shards match:
-                        assertEquals(docIDToID, expectedGroups, topGroupsShards, true, false, fillFields, getScores, idvBasedImplsUsedSharded.value);
+                        AssertEquals(docIDToID, expectedGroups, topGroupsShards, true, false, fillFields, getScores, idvBasedImplsUsedSharded.value);
                         if (topGroupsShards != null)
                         {
-                            verifyShards(shards.docStarts, topGroupsShards);
+                            VerifyShards(shards.docStarts, topGroupsShards);
                         }
 
                         bool needsScores = getScores || getMaxScores || docSort == null;
@@ -1319,8 +1361,8 @@ namespace Lucene.Net.Search.Grouping
                         TopGroups<BytesRef> groupsResultBlocks;
                         if (doAllGroups && tempTopGroupsBlocks != null)
                         {
-                            assertEquals((int)tempTopGroupsBlocks.TotalGroupCount, allGroupsCollector2.GetGroupCount());
-                            groupsResultBlocks = new TopGroups<BytesRef>(tempTopGroupsBlocks, allGroupsCollector2.GetGroupCount());
+                            assertEquals((int)tempTopGroupsBlocks.TotalGroupCount, allGroupsCollector2.GroupCount);
+                            groupsResultBlocks = new TopGroups<BytesRef>(tempTopGroupsBlocks, allGroupsCollector2.GroupCount);
                         }
                         else
                         {
@@ -1356,7 +1398,7 @@ namespace Lucene.Net.Search.Grouping
                         // Get shard'd block grouping result:
                         // Block index does not index DocValues so we pass
                         // false for canUseIDV:
-                        TopGroups<BytesRef> topGroupsBlockShards = searchShards(sBlocks, shardsBlocks.subSearchers, query,
+                        TopGroups<BytesRef> topGroupsBlockShards = SearchShards(sBlocks, shardsBlocks.subSearchers, query,
                            groupSort, docSort, groupOffset, topNGroups, docOffset, docsPerGroup, getScores, getMaxScores, false, false, new ValueHolder<bool>(false));
 
                         if (expectedGroups != null)
@@ -1384,7 +1426,7 @@ namespace Lucene.Net.Search.Grouping
                                         if (groupDocsHits.GroupSortValues != null)
                                         {
                                             //Console.WriteLine("remap " + groupDocsHits.groupSortValues[groupSortIDX] + " to " + termScoreMap.get(groupDocsHits.groupSortValues[groupSortIDX]));
-                                            groupDocsHits.GroupSortValues[groupSortIDX] = termScoreMap[groupDocsHits.GroupSortValues[groupSortIDX]];
+                                            groupDocsHits.GroupSortValues[groupSortIDX] = termScoreMap[Convert.ToSingle(groupDocsHits.GroupSortValues[groupSortIDX])];
                                             assertNotNull(groupDocsHits.GroupSortValues[groupSortIDX]);
                                         }
                                     }
@@ -1403,7 +1445,7 @@ namespace Lucene.Net.Search.Grouping
                                             FieldDoc hit = (FieldDoc)_hit;
                                             if (hit.Fields != null)
                                             {
-                                                hit.Fields[docSortIDX] = termScoreMap[hit.Fields[docSortIDX]];
+                                                hit.Fields[docSortIDX] = termScoreMap[Convert.ToSingle(hit.Fields[docSortIDX])];
                                                 assertNotNull(hit.Fields[docSortIDX]);
                                             }
                                         }
@@ -1412,8 +1454,8 @@ namespace Lucene.Net.Search.Grouping
                             }
                         }
 
-                        assertEquals(docIDToIDBlocks, expectedGroups, groupsResultBlocks, false, true, true, getScores, false);
-                        assertEquals(docIDToIDBlocks, expectedGroups, topGroupsBlockShards, false, false, fillFields, getScores, false);
+                        AssertEquals(docIDToIDBlocks, expectedGroups, groupsResultBlocks, false, true, true, getScores, false);
+                        AssertEquals(docIDToIDBlocks, expectedGroups, topGroupsBlockShards, false, false, fillFields, getScores, false);
                     }
                 }
                 finally
@@ -1433,7 +1475,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void verifyShards(int[] docStarts, TopGroups<BytesRef> topGroups)
+        private void VerifyShards(int[] docStarts, ITopGroups<BytesRef> topGroups)
         {
             foreach (var group in topGroups.Groups)
             {
@@ -1447,7 +1489,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private TopGroups<BytesRef> searchShards(IndexSearcher topSearcher, ShardSearcher[] subSearchers, Query query, Sort groupSort, Sort docSort, int groupOffset, int topNGroups, int docOffset,
+        private TopGroups<BytesRef> SearchShards(IndexSearcher topSearcher, ShardSearcher[] subSearchers, Query query, Sort groupSort, Sort docSort, int groupOffset, int topNGroups, int docOffset,
                                                  int topNDocs, bool getScores, bool getMaxScores, bool canUseIDV, bool preFlex, ValueHolder<bool> usedIdvBasedImpl)
         {
 
@@ -1459,9 +1501,9 @@ namespace Lucene.Net.Search.Grouping
             }
             // Run 1st pass collector to get top groups per shard
             Weight w = topSearcher.CreateNormalizedWeight(query);
-            List<ICollection<SearchGroup<BytesRef>>> shardGroups = new List<ICollection<SearchGroup<BytesRef>>>();
-            List < AbstractFirstPassGroupingCollector <?>> firstPassGroupingCollectors = new ArrayList<>();
-            AbstractFirstPassGroupingCollector <?> firstPassCollector = null;
+            List<IEnumerable<ISearchGroup<BytesRef>>> shardGroups = new List<IEnumerable<ISearchGroup<BytesRef>>>();
+            List<IAbstractFirstPassGroupingCollector<IComparable>> firstPassGroupingCollectors = new List<IAbstractFirstPassGroupingCollector<IComparable>>();
+            IAbstractFirstPassGroupingCollector<IComparable> firstPassCollector = null;
             bool shardsCanUseIDV;
             if (canUseIDV)
             {
@@ -1479,7 +1521,7 @@ namespace Lucene.Net.Search.Grouping
                 shardsCanUseIDV = false;
             }
 
-            String groupField = "group";
+            string groupField = "group";
             if (shardsCanUseIDV && Random().nextBoolean())
             {
                 groupField += "_dv";
@@ -1493,11 +1535,11 @@ namespace Lucene.Net.Search.Grouping
                 // all other shards match that:
                 if (firstPassCollector == null)
                 {
-                    firstPassCollector = createRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
+                    firstPassCollector = CreateRandomFirstPassCollector(groupField, groupSort, groupOffset + topNGroups);
                 }
                 else
                 {
-                    firstPassCollector = createFirstPassCollector(groupField, groupSort, groupOffset + topNGroups, firstPassCollector);
+                    firstPassCollector = CreateFirstPassCollector(groupField, groupSort, groupOffset + topNGroups, firstPassCollector);
                 }
                 if (VERBOSE)
                 {
@@ -1505,16 +1547,18 @@ namespace Lucene.Net.Search.Grouping
                     Console.WriteLine("    1st pass collector=" + firstPassCollector);
                 }
                 firstPassGroupingCollectors.Add(firstPassCollector);
-                subSearchers[shardIDX].Search(w, firstPassCollector);
-                ICollection<SearchGroup<BytesRef>> topGroups = getSearchGroups(firstPassCollector, 0, true);
+                // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                subSearchers[shardIDX].Search(w, firstPassCollector as Collector);
+                IEnumerable<ISearchGroup<BytesRef>> topGroups = GetSearchGroups(firstPassCollector, 0, true);
                 if (topGroups != null)
                 {
                     if (VERBOSE)
                     {
-                        Console.WriteLine("  shard " + shardIDX + " s=" + subSearchers[shardIDX] + " totalGroupedHitCount=?" + " " + topGroups.size() + " groups:");
+                        Console.WriteLine("  shard " + shardIDX + " s=" + subSearchers[shardIDX] + " totalGroupedHitCount=?" + " " + topGroups.Count() + " groups:");
                         foreach (SearchGroup<BytesRef> group in topGroups)
                         {
-                            Console.WriteLine("    " + groupToString(group.groupValue) + " groupSort=" + Arrays.ToString(group.sortValues));
+                            Console.WriteLine("    " + GroupToString(group.GroupValue) + " groupSort=" + Arrays.ToString(group.SortValues));
                         }
                     }
                     shardGroups.Add(topGroups);
@@ -1534,7 +1578,7 @@ namespace Lucene.Net.Search.Grouping
                     Console.WriteLine("    " + mergedTopGroups.size() + " top groups:");
                     foreach (SearchGroup<BytesRef> group in mergedTopGroups)
                     {
-                        Console.WriteLine("    [" + groupToString(group.groupValue) + "] groupSort=" + Arrays.ToString(group.sortValues));
+                        Console.WriteLine("    [" + GroupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.SortValues));
                     }
                 }
             }
@@ -1542,19 +1586,21 @@ namespace Lucene.Net.Search.Grouping
             if (mergedTopGroups != null)
             {
                 // Now 2nd pass:
-                TopGroups<BytesRef>[] shardTopGroups = new TopGroups<BytesRef>[subSearchers.Length];
+                ITopGroups<BytesRef>[] shardTopGroups = new ITopGroups<BytesRef>[subSearchers.Length];
                 for (int shardIDX = 0; shardIDX < subSearchers.Length; shardIDX++)
                 {
-                    AbstractSecondPassGroupingCollector <?> secondPassCollector = createSecondPassCollector(firstPassGroupingCollectors.get(shardIDX),
+                    IAbstractSecondPassGroupingCollector<IComparable> secondPassCollector = CreateSecondPassCollector(firstPassGroupingCollectors[shardIDX],
                         groupField, mergedTopGroups, groupSort, docSort, docOffset + topNDocs, getScores, getMaxScores, true);
-                    subSearchers[shardIDX].Search(w, secondPassCollector);
-                    shardTopGroups[shardIDX] = getTopGroups(secondPassCollector, 0);
+                    // LUCENENET TODO: Create an ICollector interface that we can inherit our Collector interfaces from
+                    // so this cast is not necessary. Consider eliminating the Collector abstract class.
+                    subSearchers[shardIDX].Search(w, secondPassCollector as Collector);
+                    shardTopGroups[shardIDX] = GetTopGroups(secondPassCollector, 0);
                     if (VERBOSE)
                     {
                         Console.WriteLine(" " + shardTopGroups[shardIDX].Groups.Length + " shard[" + shardIDX + "] groups:");
                         foreach (GroupDocs<BytesRef> group in shardTopGroups[shardIDX].Groups)
                         {
-                            Console.WriteLine("    [" + groupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.GroupSortValues) + " numDocs=" + group.ScoreDocs.Length);
+                            Console.WriteLine("    [" + GroupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.GroupSortValues) + " numDocs=" + group.ScoreDocs.Length);
                         }
                     }
                 }
@@ -1566,7 +1612,7 @@ namespace Lucene.Net.Search.Grouping
                     Console.WriteLine(" " + mergedGroups.Groups.Length + " merged groups:");
                     foreach (GroupDocs<BytesRef> group in mergedGroups.Groups)
                     {
-                        Console.WriteLine("    [" + groupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.GroupSortValues) + " numDocs=" + group.ScoreDocs.Length);
+                        Console.WriteLine("    [" + GroupToString(group.GroupValue) + "] groupSort=" + Arrays.ToString(group.GroupSortValues) + " numDocs=" + group.ScoreDocs.Length);
                     }
                 }
                 return mergedGroups;
@@ -1577,7 +1623,7 @@ namespace Lucene.Net.Search.Grouping
             }
         }
 
-        private void assertEquals(FieldCache.Ints docIDtoID, TopGroups<BytesRef> expected, TopGroups<BytesRef> actual, bool verifyGroupValues, bool verifyTotalGroupCount, bool verifySortValues, bool testScores, bool idvBasedImplsUsed)
+        private void AssertEquals(FieldCache.Ints docIDtoID, ITopGroups<BytesRef> expected, ITopGroups<BytesRef> actual, bool verifyGroupValues, bool verifyTotalGroupCount, bool verifySortValues, bool testScores, bool idvBasedImplsUsed)
         {
             if (expected == null)
             {
@@ -1600,8 +1646,8 @@ namespace Lucene.Net.Search.Grouping
                 {
                     Console.WriteLine("  check groupIDX=" + groupIDX);
                 }
-                GroupDocs<BytesRef> expectedGroup = expected.Groups[groupIDX];
-                GroupDocs<BytesRef> actualGroup = actual.Groups[groupIDX];
+                IGroupDocs<BytesRef> expectedGroup = expected.Groups[groupIDX];
+                IGroupDocs<BytesRef> actualGroup = actual.Groups[groupIDX];
                 if (verifyGroupValues)
                 {
                     if (idvBasedImplsUsed)
@@ -1664,7 +1710,8 @@ namespace Lucene.Net.Search.Grouping
             public ShardSearcher(AtomicReaderContext ctx, IndexReaderContext parent)
                             : base(parent)
             {
-                this.ctx = Collections.SingletonList(ctx);
+                //this.ctx = Collections.SingletonList(ctx);
+                this.ctx = new List<AtomicReaderContext>(new AtomicReaderContext[] { ctx });
             }
 
             public void Search(Weight weight, Collector collector)


[26/58] [abbrv] lucenenet git commit: Fixed bug in Core.Util.Mutable.MutableValue - default value of Exists property was not being set to true.

Posted by ni...@apache.org.
Fixed bug in Core.Util.Mutable.MutableValue - default value of Exists property was not being set to true.


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

Branch: refs/heads/grouping
Commit: 8af1037d09e94a62f5a9efae3e1ceba6f6ec0ada
Parents: 8cc1a3f
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Wed Nov 2 23:05:15 2016 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Nov 8 02:24:52 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Util/Mutable/MutableValue.cs | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8af1037d/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs b/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
index 328a080..66334b3 100644
--- a/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
+++ b/src/Lucene.Net.Core/Util/Mutable/MutableValue.cs
@@ -26,6 +26,11 @@ namespace Lucene.Net.Util.Mutable
     /// </summary>
     public abstract class MutableValue : IComparable<MutableValue>
     {
+        protected MutableValue()
+        {
+            Exists = true;
+        }
+
         public bool Exists { get; set; }
 
         public abstract void Copy(MutableValue source);