You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ar...@apache.org on 2009/11/03 19:06:38 UTC

svn commit: r832486 [28/29] - in /incubator/lucene.net/trunk/C#/src: ./ Demo/DeleteFiles/ Demo/DemoLib/ Demo/IndexFiles/ Demo/IndexHtml/ Demo/SearchFiles/ Lucene.Net/ Lucene.Net/Analysis/ Lucene.Net/Document/ Lucene.Net/Index/ Lucene.Net/Search/ Lucene...

Modified: incubator/lucene.net/trunk/C#/src/Test/TestSearchForDuplicates.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/TestSearchForDuplicates.cs?rev=832486&r1=832485&r2=832486&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/TestSearchForDuplicates.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Test/TestSearchForDuplicates.cs Tue Nov  3 18:06:27 2009
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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.
@@ -19,13 +19,12 @@
 
 using NUnit.Framework;
 
+using Lucene.Net.Analysis;
 using Lucene.Net.Documents;
 using Lucene.Net.Index;
 using Lucene.Net.QueryParsers;
 using Lucene.Net.Store;
-using Lucene.Net.Analysis;
 using Lucene.Net.Search;
-using Searchable = Lucene.Net.Search.Searchable;
 using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
 
 namespace Lucene.Net
@@ -35,17 +34,17 @@
 	/// <summary>JUnit adaptation of an older test case DocTest.
 	/// 
 	/// </summary>
-	/// <version>  $Id: TestSearchForDuplicates.java 583534 2007-10-10 16:46:35Z mikemccand $
+	/// <version>  $Id: TestSearchForDuplicates.java 694004 2008-09-10 21:38:52Z mikemccand $
 	/// </version>
-	[TestFixture]
-	public class TestSearchForDuplicates : LuceneTestCase
+    [TestFixture]
+    public class TestSearchForDuplicates : LuceneTestCase
 	{
 		
 		/// <summary>Main for running test case by itself. </summary>
 		[STAThread]
 		public static void  Main(System.String[] args)
 		{
-			// NUnit.Core.TestRunner.Run(new NUnit.Core.TestSuite(typeof(TestSearchForDuplicates)));    // {{Aroush-1.9}} where is 'TestRunner' in NUnit
+			// TestRunner.run(new TestSuite(typeof(TestSearchForDuplicates))); {{Aroush-2.9}} how is this done in NUnit?
 		}
 		
 		
@@ -65,7 +64,7 @@
 		/// without really knowing if the output is correct. Someone needs to
 		/// validate this output and make any changes to the checkHits method.
 		/// </summary>
-		[Test]
+        [Test]
 		public virtual void  TestRun()
 		{
 			System.IO.MemoryStream sw = new System.IO.MemoryStream();
@@ -99,7 +98,7 @@
 			
 			for (int j = 0; j < MAX_DOCS; j++)
 			{
-				Lucene.Net.Documents.Document d = new Lucene.Net.Documents.Document();
+				Document d = new Document();
 				d.Add(new Field(PRIORITY_FIELD, HIGH_PRIORITY, Field.Store.YES, Field.Index.ANALYZED));
 				d.Add(new Field(ID_FIELD, System.Convert.ToString(j), Field.Store.YES, Field.Index.ANALYZED));
 				writer.AddDocument(d);
@@ -109,7 +108,7 @@
 			// try a search without OR
 			Searcher searcher = new IndexSearcher(directory);
 			
-			Lucene.Net.QueryParsers.QueryParser parser = new Lucene.Net.QueryParsers.QueryParser(PRIORITY_FIELD, analyzer);
+			QueryParser parser = new QueryParser(PRIORITY_FIELD, analyzer);
 			
 			Query query = parser.Parse(HIGH_PRIORITY);
 			out_Renamed.WriteLine("Query: " + query.ToString(PRIORITY_FIELD));
@@ -124,7 +123,7 @@
 			searcher = new IndexSearcher(directory);
 			hits = null;
 			
-			parser = new Lucene.Net.QueryParsers.QueryParser(PRIORITY_FIELD, analyzer);
+			parser = new QueryParser(PRIORITY_FIELD, analyzer);
 			
 			query = parser.Parse(HIGH_PRIORITY + " OR " + MED_PRIORITY);
 			out_Renamed.WriteLine("Query: " + query.ToString(PRIORITY_FIELD));
@@ -144,7 +143,7 @@
 			{
 				if (i < 10 || (i > 94 && i < 105))
 				{
-					Lucene.Net.Documents.Document d = searcher.Doc(hits[i].doc);
+					Document d = searcher.Doc(hits[i].doc);
 					out_Renamed.WriteLine(i + " " + d.Get(ID_FIELD));
 				}
 			}
@@ -157,7 +156,7 @@
 			{
 				if (i < 10 || (i > 94 && i < 105))
 				{
-					Lucene.Net.Documents.Document d = searcher.Doc(hits[i].doc);
+					Document d = searcher.Doc(hits[i].doc);
 					Assert.AreEqual(System.Convert.ToString(i), d.Get(ID_FIELD), "check " + i);
 				}
 			}

Modified: incubator/lucene.net/trunk/C#/src/Test/TestSnapshotDeletionPolicy.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/TestSnapshotDeletionPolicy.cs?rev=832486&r1=832485&r2=832486&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/TestSnapshotDeletionPolicy.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Test/TestSnapshotDeletionPolicy.cs Tue Nov  3 18:06:27 2009
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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.
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
+// Intentionally not in Lucene.Net.Index, to assert
+// that we do not require any package private access.
+
 using System;
 
 using NUnit.Framework;
 
+using StandardAnalyzer = Lucene.Net.Analysis.Standard.StandardAnalyzer;
 using Document = Lucene.Net.Documents.Document;
 using Field = Lucene.Net.Documents.Field;
 using IndexCommit = Lucene.Net.Index.IndexCommit;
@@ -29,10 +33,9 @@
 using FSDirectory = Lucene.Net.Store.FSDirectory;
 using IndexInput = Lucene.Net.Store.IndexInput;
 using MockRAMDirectory = Lucene.Net.Store.MockRAMDirectory;
+using TestIndexWriter = Lucene.Net.Index.TestIndexWriter;
 using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
 using _TestUtil = Lucene.Net.Util._TestUtil;
-using StandardAnalyzer = Lucene.Net.Analysis.Standard.StandardAnalyzer;
-using TestIndexWriter = Lucene.Net.Index.TestIndexWriter;
 
 namespace Lucene.Net
 {
@@ -42,10 +45,10 @@
 	// http://lucenebook.com
 	//
 	
-	[TestFixture]
-	public class TestSnapshotDeletionPolicy : LuceneTestCase
+    [TestFixture]
+	public class TestSnapshotDeletionPolicy:LuceneTestCase
 	{
-		private class AnonymousClassThread : SupportClass.ThreadClass
+		private class AnonymousClassThread:SupportClass.ThreadClass
 		{
 			public AnonymousClassThread(long stopTime, Lucene.Net.Index.IndexWriter writer, TestSnapshotDeletionPolicy enclosingInstance)
 			{
@@ -72,7 +75,7 @@
 			{
 				Document doc = new Document();
 				doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-				while ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 < stopTime)
+				while (System.DateTime.Now.Millisecond < stopTime)
 				{
 					for (int i = 0; i < 27; i++)
 					{
@@ -82,30 +85,33 @@
 						}
 						catch (System.Exception t)
 						{
-                            System.Console.Out.WriteLine(t.StackTrace);
-                            Assert.Fail("addDocument failed");
+							System.Console.Out.WriteLine(t.StackTrace);
+							Assert.Fail("addDocument failed");
 						}
 					}
 					try
 					{
 						System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 1));
 					}
-					catch (System.Threading.ThreadInterruptedException)
+					catch (System.Threading.ThreadInterruptedException ie)
 					{
 						SupportClass.ThreadClass.Current().Interrupt();
+						throw new System.SystemException("", ie);
 					}
 				}
 			}
 		}
 		public const System.String INDEX_PATH = "test.snapshots";
 		
-		[Test]
-		public virtual void  TestSnapshotDeletionPolicy_Renamed_Method()
+        [Test]
+		public virtual void  TestSnapshotDeletionPolicy_Renamed()
 		{
 			System.IO.FileInfo dir = new System.IO.FileInfo(System.IO.Path.Combine(SupportClass.AppSettings.Get("tempDir", ""), INDEX_PATH));
 			try
 			{
-				Directory fsDir = FSDirectory.GetDirectory(dir);
+				// Sometimes past test leaves the dir
+				_TestUtil.RmDir(dir);
+				Directory fsDir = FSDirectory.Open(dir);
 				RunTest(fsDir);
 				fsDir.Close();
 			}
@@ -116,52 +122,53 @@
 			
 			MockRAMDirectory dir2 = new MockRAMDirectory();
 			RunTest(dir2);
+			dir2.Close();
 		}
-
+		
         [Test]
-        public void TestReuseAcrossWriters()
-        {
-            Directory dir = new MockRAMDirectory();
-
-            SnapshotDeletionPolicy dp = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy());
-            IndexWriter writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
-            // Force frequent commits
-            writer.SetMaxBufferedDocs(2);
-            Document doc = new Document();
-            doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            for (int i = 0; i < 7; i++)
-                writer.AddDocument(doc);
-            IndexCommit cp = (IndexCommit)dp.Snapshot();
-            CopyFiles(dir, cp);
-            writer.Close();
-            CopyFiles(dir, cp);
-
-            writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
-            CopyFiles(dir, cp);
-            for (int i = 0; i < 7; i++)
-                writer.AddDocument(doc);
-            CopyFiles(dir, cp);
-            writer.Close();
-            CopyFiles(dir, cp);
-            dp.Release();
-            writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
-            writer.Close();
-            try
-            {
-                CopyFiles(dir, cp);
-                Assert.Fail("did not hit expected IOException");
-            }
-            catch (System.IO.IOException)
-            {
-                // expected
-            }
-            dir.Close();
-        }
-
-        private void RunTest(Directory dir)
+		public virtual void  TestReuseAcrossWriters()
+		{
+			Directory dir = new MockRAMDirectory();
+			
+			SnapshotDeletionPolicy dp = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy());
+			IndexWriter writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
+			// Force frequent commits
+			writer.SetMaxBufferedDocs(2);
+			Document doc = new Document();
+			doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+			for (int i = 0; i < 7; i++)
+				writer.AddDocument(doc);
+			IndexCommit cp = (IndexCommit) dp.Snapshot();
+			CopyFiles(dir, cp);
+			writer.Close();
+			CopyFiles(dir, cp);
+			
+			writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
+			CopyFiles(dir, cp);
+			for (int i = 0; i < 7; i++)
+				writer.AddDocument(doc);
+			CopyFiles(dir, cp);
+			writer.Close();
+			CopyFiles(dir, cp);
+			dp.Release();
+			writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
+			writer.Close();
+			try
+			{
+				CopyFiles(dir, cp);
+				Assert.Fail("did not hit expected IOException");
+			}
+			catch (System.IO.IOException ioe)
+			{
+				// expected
+			}
+			dir.Close();
+		}
+		
+		private void  RunTest(Directory dir)
 		{
 			// Run for ~7 seconds
-			long stopTime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000 + 7000;
+			long stopTime = System.DateTime.Now.Millisecond + 7000;
 			
 			SnapshotDeletionPolicy dp = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy());
 			IndexWriter writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp);
@@ -175,29 +182,15 @@
 			
 			// While the above indexing thread is running, take many
 			// backups:
-			while ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 < stopTime)
+			while (System.DateTime.Now.Millisecond < stopTime)
 			{
 				BackupIndex(dir, dp);
-				try
-				{
-					System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 20));
-				}
-				catch (System.Threading.ThreadInterruptedException)
-				{
-					SupportClass.ThreadClass.Current().Interrupt();
-				}
+				System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 20));
 				if (!t.IsAlive)
 					break;
 			}
 			
-			try
-			{
-				t.Join();
-			}
-			catch (System.Threading.ThreadInterruptedException)
-			{
-				SupportClass.ThreadClass.Current().Interrupt();
-			}
+			t.Join();
 			
 			// Add one more document to force writer to commit a
 			// final segment, so deletion policy has a chance to
@@ -220,30 +213,31 @@
 		/// </summary>
 		public virtual void  BackupIndex(Directory dir, SnapshotDeletionPolicy dp)
 		{
-			
 			// To backup an index we first take a snapshot:
-            try
-            {
-                CopyFiles(dir, (IndexCommit)dp.Snapshot());
-            }
-            finally
-            {
-                // Make sure to release the snapshot, otherwise these files will never be
-                // deleted during this IndexWriter session.
-                dp.Release();
-            }
-        }
-
-        private void CopyFiles(Directory dir, IndexCommit cp)
-        {
-			// While we hold the snapshot, and no matter how long
+			try
+			{
+				CopyFiles(dir, (IndexCommit) dp.Snapshot());
+			}
+			finally
+			{
+				// Make sure to release the snapshot, otherwise these
+				// files will never be deleted during this IndexWriter
+				// session:
+				dp.Release();
+			}
+		}
+		
+		private void  CopyFiles(Directory dir, IndexCommit cp)
+		{
+			
+			// While we hold the snapshot, and nomatter how long
 			// we take to do the backup, the IndexWriter will
 			// never delete the files in the snapshot:
-			System.Collections.Generic.ICollection<string> files = cp.GetFileNames();
-			System.Collections.Generic.IEnumerator<string> it = files.GetEnumerator();
+			System.Collections.ICollection files = cp.GetFileNames();
+			System.Collections.IEnumerator it = files.GetEnumerator();
 			while (it.MoveNext())
 			{
-				string fileName = it.Current;
+				System.String fileName = (System.String) it.Current;
 				// NOTE: in a real backup you would not use
 				// readFile; you would need to use something else
 				// that copies the file to a backup location.  This
@@ -278,14 +272,7 @@
 				// make sure we are exercising the fact that the
 				// IndexWriter should not delete this file even when I
 				// take my time reading it.
-				try
-				{
-					System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 1));
-				}
-				catch (System.Threading.ThreadInterruptedException)
-				{
-					SupportClass.ThreadClass.Current().Interrupt();
-				}
+				System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 1));
 			}
 			finally
 			{

Added: incubator/lucene.net/trunk/C#/src/Test/Util/ArrayUtilTest.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/ArrayUtilTest.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/ArrayUtilTest.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/ArrayUtilTest.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,95 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+namespace Lucene.Net.Util
+{
+	
+	
+	/// <summary> 
+	/// 
+	/// 
+	/// </summary>
+    [TestFixture]
+	public class ArrayUtilTest:LuceneTestCase
+	{
+		
+        [Test]
+		public virtual void  TestParseInt()
+		{
+			int test;
+			try
+			{
+				test = ArrayUtil.ParseInt("".ToCharArray());
+				Assert.IsTrue(false);
+			}
+			catch (System.FormatException e)
+			{
+				//expected
+			}
+			try
+			{
+				test = ArrayUtil.ParseInt("foo".ToCharArray());
+				Assert.IsTrue(false);
+			}
+			catch (System.FormatException e)
+			{
+				//expected
+			}
+			try
+			{
+				test = ArrayUtil.ParseInt(System.Convert.ToString(System.Int64.MaxValue).ToCharArray());
+				Assert.IsTrue(false);
+			}
+			catch (System.FormatException e)
+			{
+				//expected
+			}
+			try
+			{
+				test = ArrayUtil.ParseInt("0.34".ToCharArray());
+				Assert.IsTrue(false);
+			}
+			catch (System.FormatException e)
+			{
+				//expected
+			}
+			
+			try
+			{
+				test = ArrayUtil.ParseInt("1".ToCharArray());
+				Assert.IsTrue(test == 1, test + " does not equal: " + 1);
+				test = ArrayUtil.ParseInt("-10000".ToCharArray());
+				Assert.IsTrue(test == - 10000, test + " does not equal: " + (- 10000));
+				test = ArrayUtil.ParseInt("1923".ToCharArray());
+				Assert.IsTrue(test == 1923, test + " does not equal: " + 1923);
+				test = ArrayUtil.ParseInt("-1".ToCharArray());
+				Assert.IsTrue(test == - 1, test + " does not equal: " + (- 1));
+				test = ArrayUtil.ParseInt("foo 1923 bar".ToCharArray(), 4, 4);
+				Assert.IsTrue(test == 1923, test + " does not equal: " + 1923);
+			}
+			catch (System.FormatException e)
+			{
+				System.Console.Error.WriteLine(e.StackTrace);
+				Assert.IsTrue(false);
+			}
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Test/Util/Cache/TestSimpleLRUCache.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/Cache/TestSimpleLRUCache.cs?rev=832486&r1=832485&r2=832486&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/Cache/TestSimpleLRUCache.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/Cache/TestSimpleLRUCache.cs Tue Nov  3 18:06:27 2009
@@ -1,91 +1,77 @@
-/**
-* 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.
-*/
+/* 
+ * 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 System;
 
 using NUnit.Framework;
 
+using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+
 namespace Lucene.Net.Util.Cache
 {
-    [TestFixture]
-    public class TestSimpleLRUCache
-    {
-        [Test]
-        public void TestLRUCache()
-        {
-            int n = 100;
-            object dummy = new object();
-
-            Cache cache = new SimpleLRUCache(n);
-
-            for (int i = 0; i < n; i++)
-            {
-                cache.Put(i, dummy);
-            }
-
-            // access every 2nd item in cache
-            for (int i = 0; i < n; i += 2)
-            {
-                Assert.IsNotNull(cache.Get(i));
-            }
-
-            // add n/2 elements to cache, the ones that weren't
-            // touched in the previous loop should now be thrown away
-            for (int i = n; i < n + (n / 2); i++)
-            {
-                cache.Put(i, dummy);
-            }
-
-            // access every 4th item in cache
-            for (int i = 0; i < n; i += 4)
-            {
-                Assert.IsNotNull(cache.Get(i));
-            }
-
-            // add 3/4n elements to cache, the ones that weren't
-            // touched in the previous loops should now be thrown away
-            for (int i = n; i < n + (n * 3 / 4); i++)
-            {
-                cache.Put(i, dummy);
-            }
-
-            // access every 4th item in cache
-            for (int i = 0; i < n; i += 4)
-            {
-                Assert.IsNotNull(cache.Get(i));
-            }
-        }
-
-        [Test]
-        public void TestLRUCache_LUCENENET_190()
-        {
-            SimpleLRUCache cache = new SimpleLRUCache(3);
-                                                        //Item=>LastAccessTime
-            cache.Put("a", "a");                        //a=>1
-            cache.Put("b", "b");                        //b=>2
-            cache.Put("c", "c");                        //c=>3
-            Assert.IsNotNull(cache.Get("a"), "DBG1");   //a=>4
-            Assert.IsNotNull(cache.Get("b"), "DBG2");   //b=>5
-            Assert.IsNotNull(cache.Get("c"), "DBG3");   //c=>6
-            cache.Put("d", "d");                        //d=>7 ,remove a
-            Assert.IsNull(cache.Get("a"), "DBG4");      //a is removed already
-            Assert.IsNotNull(cache.Get("c"), "DBG5");   //c=>8
-            cache.Put("e", "e");                        //e=>9 ,remove b
-            cache.Put("f", "f");                        //f=>10 ,remove d
-            Assert.IsNotNull(cache.Get("c"), "DBG6");   //c=>11
-                                                        //final cache: e=>9,f=>10,c=>11
-        }
-    }
-}
+	
+	[TestFixture]
+	public class TestSimpleLRUCache:LuceneTestCase
+	{
+		
+		[Test]
+		public virtual void  TestLRUCache()
+		{
+			int n = 100;
+			System.Object dummy = new System.Object();
+			
+			Cache cache = new SimpleLRUCache(n);
+			
+			for (int i = 0; i < n; i++)
+			{
+				cache.Put((System.Object) i, dummy);
+			}
+			
+			// access every 2nd item in cache
+			for (int i = 0; i < n; i += 2)
+			{
+				Assert.IsNotNull(cache.Get((System.Object) i));
+			}
+			
+			// add n/2 elements to cache, the ones that weren't
+			// touched in the previous loop should now be thrown away
+			for (int i = n; i < n + (n / 2); i++)
+			{
+				cache.Put((System.Object) i, dummy);
+			}
+			
+			// access every 4th item in cache
+			for (int i = 0; i < n; i += 4)
+			{
+				Assert.IsNotNull(cache.Get((System.Object) i));
+			}
+			
+			// add 3/4n elements to cache, the ones that weren't
+			// touched in the previous loops should now be thrown away
+			for (int i = n; i < n + (n * 3 / 4); i++)
+			{
+				cache.Put((System.Object) i, dummy);
+			}
+			
+			// access every 4th item in cache
+			for (int i = 0; i < n; i += 4)
+			{
+				Assert.IsNotNull(cache.Get((System.Object) i));
+			}
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Test/Util/English.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/English.cs?rev=832486&r1=832485&r2=832486&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/English.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/English.cs Tue Nov  3 18:06:27 2009
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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.
@@ -17,6 +17,8 @@
 
 using System;
 
+using NUnit.Framework;
+
 namespace Lucene.Net.Util
 {
 	

Added: incubator/lucene.net/trunk/C#/src/Test/Util/LocalizedTestCase.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/LocalizedTestCase.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/LocalizedTestCase.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/LocalizedTestCase.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,117 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+namespace Lucene.Net.Util
+{
+	
+	/// <summary> Base test class for Lucene test classes that test Locale-sensitive behavior.
+	/// <p>
+	/// This class will run tests under the default Locale, but then will also run
+	/// tests under all available JVM locales. This is helpful to ensure tests will
+	/// not fail under a different environment.
+	/// </p>
+	/// </summary>
+    [TestFixture]
+	public abstract class LocalizedTestCase:LuceneTestCase
+	{
+		/// <summary> Before changing the default Locale, save the default Locale here so that it
+		/// can be restored.
+		/// </summary>
+		private System.Globalization.CultureInfo defaultLocale = System.Threading.Thread.CurrentThread.CurrentCulture;
+		
+		/// <summary> The locale being used as the system default Locale</summary>
+		private System.Globalization.CultureInfo locale;
+		
+		/// <summary> An optional limited set of testcases that will run under different Locales.</summary>
+		private System.Collections.Hashtable testWithDifferentLocales;
+		
+		public LocalizedTestCase():base()
+		{
+			testWithDifferentLocales = null;
+		}
+		
+		public LocalizedTestCase(System.String name):base(name)
+		{
+			testWithDifferentLocales = null;
+		}
+		
+		public LocalizedTestCase(System.Collections.Hashtable testWithDifferentLocales):base()
+		{
+			this.testWithDifferentLocales = testWithDifferentLocales;
+		}
+		
+		public LocalizedTestCase(System.String name, System.Collections.Hashtable testWithDifferentLocales):base(name)
+		{
+			this.testWithDifferentLocales = testWithDifferentLocales;
+		}
+		
+		// @Override
+		[Test]
+		public override void  SetUp()
+		{
+			base.SetUp();
+			System.Threading.Thread.CurrentThread.CurrentCulture = locale;
+		}
+		
+		// @Override
+		[TearDown]
+		public override void  TearDown()
+		{
+			System.Threading.Thread.CurrentThread.CurrentCulture = defaultLocale;
+			base.TearDown();
+		}
+		
+		// @Override
+		public override void  RunBare()
+		{
+			// Do the test with the default Locale (default)
+			try
+			{
+				locale = defaultLocale;
+				base.RunBare();
+			}
+			catch (System.Exception e)
+			{
+				System.Console.Out.WriteLine("Test failure of '" + "getName()" + "' occurred with the default Locale " + locale); // {{Aroush-2.9}} String junit.framework.TestCase.getName()
+				throw e;
+			}
+			
+			if (testWithDifferentLocales == null || testWithDifferentLocales.Contains("getName()")) // {{Aroush-2.9}} String junit.framework.TestCase.getName()
+			{
+				// Do the test again under different Locales
+				System.Globalization.CultureInfo[] systemLocales = System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.InstalledWin32Cultures);
+				for (int i = 0; i < systemLocales.Length; i++)
+				{
+					try
+					{
+						locale = systemLocales[i];
+						base.RunBare();
+					}
+					catch (System.Exception e)
+					{
+						System.Console.Out.WriteLine("Test failure of '" + "getName()" + "' occurred under a different Locale " + locale); // {{Aroush-2.9}} String junit.framework.TestCase.getName()
+						throw e;
+					}
+				}
+			}
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Test/Util/LuceneTestCase.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/LuceneTestCase.cs?rev=832486&r1=832485&r2=832486&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/LuceneTestCase.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/LuceneTestCase.cs Tue Nov  3 18:06:27 2009
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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.
@@ -19,30 +19,45 @@
 
 using NUnit.Framework;
 
+using TokenStream = Lucene.Net.Analysis.TokenStream;
 using ConcurrentMergeScheduler = Lucene.Net.Index.ConcurrentMergeScheduler;
+using Insanity = Lucene.Net.Util.FieldCacheSanityChecker.Insanity;
+using FieldCache = Lucene.Net.Search.FieldCache;
+using CacheEntry = Lucene.Net.Search.CacheEntry;
 
 namespace Lucene.Net.Util
 {
 	
-	/// <summary>Base class for all Lucene unit tests.  Currently the
+	/// <summary> Base class for all Lucene unit tests.  
+	/// <p>
+	/// Currently the
 	/// only added functionality over JUnit's TestCase is
 	/// asserting that no unhandled exceptions occurred in
-	/// threads launched by ConcurrentMergeScheduler.  If you
+	/// threads launched by ConcurrentMergeScheduler and asserting sane
+	/// FieldCache usage athe moment of tearDown.
+	/// </p>
+	/// <p>
+	/// If you
 	/// override either <code>setUp()</code> or
 	/// <code>tearDown()</code> in your unit test, make sure you
 	/// call <code>super.setUp()</code> and
-	/// <code>super.tearDown()</code>.
+	/// <code>super.tearDown()</code>
+	/// </p>
 	/// </summary>
-	
-	[TestFixture]
-	public /*abstract*/ class LuceneTestCase
+	/// <seealso cref="assertSaneFieldCaches">
+	/// </seealso>
+	[Serializable]
+	public abstract class LuceneTestCase
 	{
 		
-		public LuceneTestCase() : base()
+		[NonSerialized]
+		private bool savedAPISetting = false;
+		
+		public LuceneTestCase():base()
 		{
 		}
 		
-		public LuceneTestCase(System.String name) : base()
+		public LuceneTestCase(System.String name)
 		{
 		}
 		
@@ -50,23 +65,201 @@
 		public virtual void  SetUp()
 		{
 			ConcurrentMergeScheduler.SetTestMode();
+			
+			savedAPISetting = TokenStream.GetOnlyUseNewAPI();
+			TokenStream.SetOnlyUseNewAPI(false);
+		}
+		
+		/// <summary> Forcible purges all cache entries from the FieldCache.
+		/// <p>
+		/// This method will be called by tearDown to clean up FieldCache.DEFAULT.
+		/// If a (poorly written) test has some expectation that the FieldCache
+		/// will persist across test methods (ie: a static IndexReader) this 
+		/// method can be overridden to do nothing.
+		/// </p>
+		/// </summary>
+		/// <seealso cref="FieldCache.PurgeAllCaches()">
+		/// </seealso>
+		protected internal virtual void  PurgeFieldCache(FieldCache fc)
+		{
+			fc.PurgeAllCaches();
+		}
+		
+		protected internal virtual System.String GetTestLabel()
+		{
+			return GetType().Name + "." + "getName()"; // {{Aroush-2.9}} String junit.framework.TestCase.getName()
 		}
 		
 		[TearDown]
 		public virtual void  TearDown()
 		{
-			if (ConcurrentMergeScheduler.AnyUnhandledExceptions())
+			try
+			{
+				// this isn't as useful as calling directly from the scope where the 
+				// index readers are used, because they could be gc'ed just before
+				// tearDown is called.
+				// But it's better then nothing.
+				AssertSaneFieldCaches(GetTestLabel());
+				
+				if (ConcurrentMergeScheduler.AnyUnhandledExceptions())
+				{
+					// Clear the failure so that we don't just keep
+					// failing subsequent test cases
+					ConcurrentMergeScheduler.ClearUnhandledExceptions();
+					Assert.Fail("ConcurrentMergeScheduler hit unhandled exceptions");
+				}
+			}
+			finally
 			{
-                // clear the failure so that we don't just keep failing subsequent test cases
-                ConcurrentMergeScheduler.ClearUnhandledExceptions();
-				Assert.Fail("ConcurrentMergeScheduler hit unhandled exceptions");
+				PurgeFieldCache(Lucene.Net.Search.FieldCache_Fields.DEFAULT);
 			}
+			
+			TokenStream.SetOnlyUseNewAPI(savedAPISetting);
+			//base.TearDown();  // {{Aroush-2.9}}
 		}
-
-		[Test]
-		public virtual void  TestDummy()
+		
+		/// <summary> Asserts that FieldCacheSanityChecker does not detect any 
+		/// problems with FieldCache.DEFAULT.
+		/// <p>
+		/// If any problems are found, they are logged to System.err 
+		/// (allong with the msg) when the Assertion is thrown.
+		/// </p>
+		/// <p>
+		/// This method is called by tearDown after every test method, 
+		/// however IndexReaders scoped inside test methods may be garbage 
+		/// collected prior to this method being called, causing errors to 
+		/// be overlooked. Tests are encouraged to keep their IndexReaders 
+		/// scoped at the class level, or to explicitly call this method 
+		/// directly in the same scope as the IndexReader.
+		/// </p>
+		/// </summary>
+		/// <seealso cref="FieldCacheSanityChecker">
+		/// </seealso>
+		protected internal virtual void  AssertSaneFieldCaches(System.String msg)
 		{
-			// So that NUnit doesn't complain
+			CacheEntry[] entries = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetCacheEntries();
+			Insanity[] insanity = null;
+			try
+			{
+				try
+				{
+					insanity = FieldCacheSanityChecker.CheckSanity(entries);
+				}
+				catch (System.SystemException e)
+				{
+					System.IO.StreamWriter temp_writer;
+					temp_writer = new System.IO.StreamWriter(System.Console.OpenStandardError(), System.Console.Error.Encoding);
+					temp_writer.AutoFlush = true;
+					DumpArray(msg + ": FieldCache", entries, temp_writer);
+					throw e;
+				}
+				
+				Assert.AreEqual(0, insanity.Length, msg + ": Insane FieldCache usage(s) found");
+				insanity = null;
+			}
+			finally
+			{
+				
+				// report this in the event of any exception/failure
+				// if no failure, then insanity will be null anyway
+				if (null != insanity)
+				{
+					System.IO.StreamWriter temp_writer2;
+					temp_writer2 = new System.IO.StreamWriter(System.Console.OpenStandardError(), System.Console.Error.Encoding);
+					temp_writer2.AutoFlush = true;
+					DumpArray(msg + ": Insane FieldCache usage(s)", insanity, temp_writer2);
+				}
+			}
+		}
+		
+		/// <summary> Convinience method for logging an iterator.</summary>
+		/// <param name="label">String logged before/after the items in the iterator
+		/// </param>
+		/// <param name="iter">Each next() is toString()ed and logged on it's own line. If iter is null this is logged differnetly then an empty iterator.
+		/// </param>
+		/// <param name="stream">Stream to log messages to.
+		/// </param>
+		public static void  DumpIterator(System.String label, System.Collections.IEnumerator iter, System.IO.StreamWriter stream)
+		{
+			stream.WriteLine("*** BEGIN " + label + " ***");
+			if (null == iter)
+			{
+				stream.WriteLine(" ... NULL ...");
+			}
+			else
+			{
+				while (iter.MoveNext())
+				{
+					stream.WriteLine(iter.Current.ToString());
+				}
+			}
+			stream.WriteLine("*** END " + label + " ***");
 		}
+		
+		/// <summary> Convinience method for logging an array.  Wraps the array in an iterator and delegates</summary>
+		/// <seealso cref="dumpIterator(String,Iterator,PrintStream)">
+		/// </seealso>
+		public static void  DumpArray(System.String label, System.Object[] objs, System.IO.StreamWriter stream)
+		{
+			System.Collections.IEnumerator iter = (null == objs)?null:new System.Collections.ArrayList(objs).GetEnumerator();
+			DumpIterator(label, iter, stream);
+		}
+		
+		/// <summary> Returns a {@link Random} instance for generating random numbers during the test.
+		/// The random seed is logged during test execution and printed to System.out on any failure
+		/// for reproducing the test using {@link #NewRandom(long)} with the recorded seed
+		/// .
+		/// </summary>
+		public virtual System.Random NewRandom()
+		{
+			if (seed_init != false)
+			{
+				throw new System.SystemException("please call LuceneTestCase.newRandom only once per test");
+			}
+			return NewRandom(seedRnd.Next(System.Int32.MinValue, System.Int32.MaxValue));
+		}
+		
+		/// <summary> Returns a {@link Random} instance for generating random numbers during the test.
+		/// If an error occurs in the test that is not reproducible, you can use this method to
+		/// initialize the number generator with the seed that was printed out during the failing test.
+		/// </summary>
+		public virtual System.Random NewRandom(int seed)
+		{
+			if (this.seed_init != false)
+			{
+				throw new System.SystemException("please call LuceneTestCase.newRandom only once per test");
+			}
+            this.seed_init = true;
+			this.seed = seed;
+			return new System.Random(seed);
+		}
+		
+		// @Override
+		public virtual void  RunBare()
+		{
+			try
+			{
+				seed_init = false;
+				//base.RunBare(); // {{Aroush-2.9}}
+                System.Diagnostics.Debug.Fail("Port issue:", "base.RunBare()"); // {{Aroush-2.9}}
+			}
+			catch (System.Exception e)
+			{
+				if (seed_init != false)
+				{
+					System.Console.Out.WriteLine("NOTE: random seed of testcase '" + GetType() + "' was: " + seed);
+				}
+				throw e;
+			}
+		}
+		
+		// recorded seed
+		[NonSerialized]
+		protected internal int seed = 0;
+        protected internal bool seed_init = false;
+		
+		// static members
+		[NonSerialized]
+		private static readonly System.Random seedRnd = new System.Random();
 	}
 }
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Test/Util/TestAttributeSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/TestAttributeSource.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/TestAttributeSource.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/TestAttributeSource.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,142 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+using Token = Lucene.Net.Analysis.Token;
+using Lucene.Net.Analysis.Tokenattributes;
+
+namespace Lucene.Net.Util
+{
+	
+    [TestFixture]
+	public class TestAttributeSource:LuceneTestCase
+	{
+		
+        [Test]
+		public virtual void  TestCaptureState()
+		{
+			// init a first instance
+			AttributeSource src = new AttributeSource();
+			TermAttribute termAtt = (TermAttribute) src.AddAttribute(typeof(TermAttribute));
+			TypeAttribute typeAtt = (TypeAttribute) src.AddAttribute(typeof(TypeAttribute));
+			termAtt.SetTermBuffer("TestTerm");
+			typeAtt.SetType("TestType");
+			int hashCode = src.GetHashCode();
+			
+			AttributeSource.State state = src.CaptureState();
+			
+			// modify the attributes
+			termAtt.SetTermBuffer("AnotherTestTerm");
+			typeAtt.SetType("AnotherTestType");
+			Assert.IsTrue(hashCode != src.GetHashCode(), "Hash code should be different");
+			
+			src.RestoreState(state);
+			Assert.AreEqual("TestTerm", termAtt.Term());
+			Assert.AreEqual("TestType", typeAtt.Type());
+			Assert.AreEqual(hashCode, src.GetHashCode(), "Hash code should be equal after restore");
+			
+			// restore into an exact configured copy
+			AttributeSource copy = new AttributeSource();
+			copy.AddAttribute(typeof(TermAttribute));
+			copy.AddAttribute(typeof(TypeAttribute));
+			copy.RestoreState(state);
+			Assert.AreEqual(src.GetHashCode(), copy.GetHashCode(), "Both AttributeSources should have same hashCode after restore");
+			Assert.AreEqual(src, copy, "Both AttributeSources should be equal after restore");
+			
+			// init a second instance (with attributes in different order and one additional attribute)
+			AttributeSource src2 = new AttributeSource();
+			typeAtt = (TypeAttribute) src2.AddAttribute(typeof(TypeAttribute));
+			Lucene.Net.Analysis.Tokenattributes.FlagsAttribute flagsAtt = (Lucene.Net.Analysis.Tokenattributes.FlagsAttribute) src2.AddAttribute(typeof(Lucene.Net.Analysis.Tokenattributes.FlagsAttribute));
+			termAtt = (TermAttribute) src2.AddAttribute(typeof(TermAttribute));
+			flagsAtt.SetFlags(12345);
+			
+			src2.RestoreState(state);
+			Assert.AreEqual("TestTerm", termAtt.Term());
+			Assert.AreEqual("TestType", typeAtt.Type());
+			Assert.AreEqual(12345, flagsAtt.GetFlags(), "FlagsAttribute should not be touched");
+			
+			// init a third instance missing one Attribute
+			AttributeSource src3 = new AttributeSource();
+			termAtt = (TermAttribute) src3.AddAttribute(typeof(TermAttribute));
+			try
+			{
+				src3.RestoreState(state);
+				Assert.Fail("The third instance is missing the TypeAttribute, so restoreState() should throw IllegalArgumentException");
+			}
+			catch (System.ArgumentException iae)
+			{
+				// pass
+			}
+		}
+		
+        [Test]
+		public virtual void  TestCloneAttributes()
+		{
+			AttributeSource src = new AttributeSource();
+			TermAttribute termAtt = (TermAttribute) src.AddAttribute(typeof(TermAttribute));
+			TypeAttribute typeAtt = (TypeAttribute) src.AddAttribute(typeof(TypeAttribute));
+			termAtt.SetTermBuffer("TestTerm");
+			typeAtt.SetType("TestType");
+			
+			AttributeSource clone = src.CloneAttributes();
+			System.Collections.IEnumerator it = clone.GetAttributeClassesIterator();
+			Assert.AreEqual(typeof(TermAttribute), it.Current, "TermAttribute must be the first attribute");
+			Assert.AreEqual(typeof(TypeAttribute), it.Current, "TypeAttribute must be the second attribute");
+			Assert.IsFalse(it.MoveNext(), "No more attributes");
+			
+			TermAttribute termAtt2 = (TermAttribute) clone.GetAttribute(typeof(TermAttribute));
+			TypeAttribute typeAtt2 = (TypeAttribute) clone.GetAttribute(typeof(TypeAttribute));
+			Assert.AreNotEqual(termAtt2, termAtt, "TermAttribute of original and clone must be different instances");
+			Assert.AreNotEqual(typeAtt2, typeAtt, "TypeAttribute of original and clone must be different instances");
+			Assert.AreEqual(termAtt2, termAtt, "TermAttribute of original and clone must be equal");
+			Assert.AreEqual(typeAtt2, typeAtt, "TypeAttribute of original and clone must be equal");
+		}
+		
+        [Test]
+		public virtual void  TestToStringAndMultiAttributeImplementations()
+		{
+			AttributeSource src = new AttributeSource();
+			TermAttribute termAtt = (TermAttribute) src.AddAttribute(typeof(TermAttribute));
+			TypeAttribute typeAtt = (TypeAttribute) src.AddAttribute(typeof(TypeAttribute));
+			termAtt.SetTermBuffer("TestTerm");
+			typeAtt.SetType("TestType");
+			Assert.AreEqual("(" + termAtt.ToString() + "," + typeAtt.ToString() + ")", src.ToString(), "Attributes should appear in original order");
+			System.Collections.IEnumerator it = src.GetAttributeImplsIterator();
+			Assert.IsTrue(it.MoveNext(), "Iterator should have 2 attributes left");
+			Assert.AreSame(termAtt, it.Current, "First AttributeImpl from iterator should be termAtt");
+			Assert.IsTrue(it.MoveNext(), "Iterator should have 1 attributes left");
+			Assert.AreSame(typeAtt, it.Current, "Second AttributeImpl from iterator should be typeAtt");
+			Assert.IsFalse(it.MoveNext(), "Iterator should have 0 attributes left");
+			
+			src = new AttributeSource();
+			src.AddAttributeImpl(new Token());
+			// this should not add a new attribute as Token implements TermAttribute, too
+			termAtt = (TermAttribute) src.AddAttribute(typeof(TermAttribute));
+			Assert.IsTrue(termAtt is Token, "TermAttribute should be implemented by Token");
+			// get the Token attribute and check, that it is the only one
+			it = src.GetAttributeImplsIterator();
+			Token tok = (Token) it.Current;
+			Assert.IsFalse(it.MoveNext(), "There should be only one attribute implementation instance");
+			
+			termAtt.SetTermBuffer("TestTerm");
+			Assert.AreEqual("(" + tok.ToString() + ")", src.ToString(), "Token should only printed once");
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Test/Util/TestBitVector.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/TestBitVector.cs?rev=832486&r1=832485&r2=832486&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/TestBitVector.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/TestBitVector.cs Tue Nov  3 18:06:27 2009
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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.
@@ -29,11 +29,14 @@
 	/// 
 	/// 
 	/// </summary>
-	/// <version>  $Id: TestBitVector.java 583534 2007-10-10 16:46:35Z mikemccand $
+	/// <version>  $Id: TestBitVector.java 765649 2009-04-16 14:29:26Z mikemccand $
 	/// </version>
 	[TestFixture]
-	public class TestBitVector : LuceneTestCase
+	public class TestBitVector:LuceneTestCase
 	{
+		public TestBitVector(System.String s):base(s)
+		{
+		}
 		
 		/// <summary> Test the default constructor on BitVectors of various sizes.</summary>
 		/// <throws>  Exception </throws>
@@ -215,7 +218,6 @@
 				bv.Write(d, "TESTBV");
 			}
 		}
-
 		/// <summary> Compare two BitVectors.
 		/// This should really be an equals method on the BitVector itself.
 		/// </summary>
@@ -237,5 +239,76 @@
 			}
 			return equal;
 		}
+		
+		private static int[] subsetPattern = new int[]{1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1};
+		
+		/// <summary> Tests BitVector.subset() against the above pattern</summary>
+		[Test]
+		public virtual void  TestSubset()
+		{
+			DoTestSubset(0, 0);
+			DoTestSubset(0, 20);
+			DoTestSubset(0, 7);
+			DoTestSubset(0, 8);
+			DoTestSubset(0, 9);
+			DoTestSubset(0, 15);
+			DoTestSubset(0, 16);
+			DoTestSubset(0, 17);
+			DoTestSubset(1, 7);
+			DoTestSubset(1, 8);
+			DoTestSubset(1, 9);
+			DoTestSubset(1, 15);
+			DoTestSubset(1, 16);
+			DoTestSubset(1, 17);
+			DoTestSubset(2, 20);
+			DoTestSubset(3, 20);
+			DoTestSubset(4, 20);
+			DoTestSubset(5, 20);
+			DoTestSubset(6, 20);
+			DoTestSubset(7, 14);
+			DoTestSubset(7, 15);
+			DoTestSubset(7, 16);
+			DoTestSubset(8, 15);
+			DoTestSubset(9, 20);
+			DoTestSubset(10, 20);
+			DoTestSubset(11, 20);
+			DoTestSubset(12, 20);
+			DoTestSubset(13, 20);
+		}
+		
+		/// <summary> Compare a subset against the corresponding portion of the test pattern</summary>
+		private void  DoTestSubset(int start, int end)
+		{
+			BitVector full = CreateSubsetTestVector();
+			BitVector subset = full.Subset(start, end);
+			Assert.AreEqual(end - start, subset.Size());
+			int count = 0;
+			for (int i = start, j = 0; i < end; i++, j++)
+			{
+				if (subsetPattern[i] == 1)
+				{
+					count++;
+					Assert.IsTrue(subset.Get(j));
+				}
+				else
+				{
+					Assert.IsFalse(subset.Get(j));
+				}
+			}
+			Assert.AreEqual(count, subset.Count());
+		}
+		
+		private BitVector CreateSubsetTestVector()
+		{
+			BitVector bv = new BitVector(subsetPattern.Length);
+			for (int i = 0; i < subsetPattern.Length; i++)
+			{
+				if (subsetPattern[i] == 1)
+				{
+					bv.Set(i);
+				}
+			}
+			return bv;
+		}
 	}
 }
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Test/Util/TestCloseableThreadLocal.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/TestCloseableThreadLocal.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/TestCloseableThreadLocal.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/TestCloseableThreadLocal.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,83 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+namespace Lucene.Net.Util
+{
+	
+    [TestFixture]
+	public class TestCloseableThreadLocal:LuceneTestCase
+	{
+		public const System.String TEST_VALUE = "initvaluetest";
+		
+        [Test]
+		public virtual void  TestInitValue()
+		{
+			InitValueThreadLocal tl = new InitValueThreadLocal(this);
+			System.String str = (System.String) tl.Get();
+			Assert.AreEqual(TEST_VALUE, str);
+		}
+		
+        [Test]
+		public virtual void  TestNullValue()
+		{
+			// Tests that null can be set as a valid value (LUCENE-1805). This
+			// previously failed in get().
+			CloseableThreadLocal ctl = new CloseableThreadLocal();
+			ctl.Set((System.Object) null);
+			Assert.IsNull(ctl.Get());
+		}
+		
+        [Test]
+		public virtual void  TestDefaultValueWithoutSetting()
+		{
+			// LUCENE-1805: make sure default get returns null,
+			// twice in a row
+			CloseableThreadLocal ctl = new CloseableThreadLocal();
+			Assert.IsNull(ctl.Get());
+			Assert.IsNull(ctl.Get());
+		}
+		
+		public class InitValueThreadLocal:CloseableThreadLocal
+		{
+			public InitValueThreadLocal(TestCloseableThreadLocal enclosingInstance)
+			{
+				InitBlock(enclosingInstance);
+			}
+			private void  InitBlock(TestCloseableThreadLocal enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private TestCloseableThreadLocal enclosingInstance;
+			public TestCloseableThreadLocal Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			public /*protected internal*/ override System.Object InitialValue()
+			{
+				return Lucene.Net.Util.TestCloseableThreadLocal.TEST_VALUE;
+			}
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Test/Util/TestFieldCacheSanityChecker.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/TestFieldCacheSanityChecker.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/TestFieldCacheSanityChecker.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/TestFieldCacheSanityChecker.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,193 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer;
+using Document = Lucene.Net.Documents.Document;
+using Field = Lucene.Net.Documents.Field;
+using IndexReader = Lucene.Net.Index.IndexReader;
+using IndexWriter = Lucene.Net.Index.IndexWriter;
+using MultiReader = Lucene.Net.Index.MultiReader;
+using RAMDirectory = Lucene.Net.Store.RAMDirectory;
+using Insanity = Lucene.Net.Util.FieldCacheSanityChecker.Insanity;
+using InsanityType = Lucene.Net.Util.FieldCacheSanityChecker.InsanityType;
+using FieldCache = Lucene.Net.Search.FieldCache;
+
+namespace Lucene.Net.Util
+{
+	
+    [TestFixture]
+	public class TestFieldCacheSanityChecker:LuceneTestCase
+	{
+		
+		protected internal IndexReader readerA;
+		protected internal IndexReader readerB;
+		protected internal IndexReader readerX;
+		
+		private const int NUM_DOCS = 1000;
+		
+		[Test]
+		public override void  SetUp()
+		{
+			base.SetUp();
+			
+			RAMDirectory dirA = new RAMDirectory();
+			RAMDirectory dirB = new RAMDirectory();
+			
+			IndexWriter wA = new IndexWriter(dirA, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
+			IndexWriter wB = new IndexWriter(dirB, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
+			
+			long theLong = System.Int64.MaxValue;
+			double theDouble = System.Double.MaxValue;
+			byte theByte = (byte) System.SByte.MaxValue;
+			short theShort = System.Int16.MaxValue;
+			int theInt = System.Int32.MaxValue;
+			float theFloat = System.Single.MaxValue;
+			for (int i = 0; i < NUM_DOCS; i++)
+			{
+				Document doc = new Document();
+				doc.Add(new Field("theLong", System.Convert.ToString(theLong--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+				doc.Add(new Field("theDouble", System.Convert.ToString(theDouble--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+				doc.Add(new Field("theByte", System.Convert.ToString((byte) theByte--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+				doc.Add(new Field("theShort", System.Convert.ToString(theShort--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+				doc.Add(new Field("theInt", System.Convert.ToString(theInt--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+				doc.Add(new Field("theFloat", System.Convert.ToString(theFloat--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+				if (0 == i % 3)
+				{
+					wA.AddDocument(doc);
+				}
+				else
+				{
+					wB.AddDocument(doc);
+				}
+			}
+			wA.Close();
+			wB.Close();
+			readerA = IndexReader.Open(dirA);
+			readerB = IndexReader.Open(dirB);
+			readerX = new MultiReader(new IndexReader[]{readerA, readerB});
+		}
+		
+		[TearDown]
+		public override void  TearDown()
+		{
+			base.TearDown();
+			readerA.Close();
+			readerB.Close();
+			readerX.Close();
+		}
+		
+		[Test]
+		public virtual void  TestSanity()
+		{
+			FieldCache cache = Lucene.Net.Search.FieldCache_Fields.DEFAULT;
+			cache.PurgeAllCaches();
+			
+			double[] doubles;
+			int[] ints;
+			
+			doubles = cache.GetDoubles(readerA, "theDouble");
+			doubles = cache.GetDoubles(readerA, "theDouble", Lucene.Net.Search.FieldCache_Fields.DEFAULT_DOUBLE_PARSER);
+			doubles = cache.GetDoubles(readerB, "theDouble", Lucene.Net.Search.FieldCache_Fields.DEFAULT_DOUBLE_PARSER);
+			
+			ints = cache.GetInts(readerX, "theInt");
+			ints = cache.GetInts(readerX, "theInt", Lucene.Net.Search.FieldCache_Fields.DEFAULT_INT_PARSER);
+			
+			// // // 
+			
+			Insanity[] insanity = FieldCacheSanityChecker.CheckSanity(cache.GetCacheEntries());
+			
+			if (0 < insanity.Length)
+			{
+				System.IO.StreamWriter temp_writer;
+				temp_writer = new System.IO.StreamWriter(System.Console.OpenStandardError(), System.Console.Error.Encoding);
+				temp_writer.AutoFlush = true;
+				DumpArray(GetTestLabel() + " INSANITY", insanity, temp_writer);
+			}
+			
+			Assert.AreEqual(0, insanity.Length, "shouldn't be any cache insanity");
+			cache.PurgeAllCaches();
+		}
+		
+		[Test]
+		public virtual void  TestInsanity1()
+		{
+			FieldCache cache = Lucene.Net.Search.FieldCache_Fields.DEFAULT;
+			cache.PurgeAllCaches();
+			
+			int[] ints;
+			System.String[] strings;
+			byte[] bytes;
+			
+			ints = cache.GetInts(readerX, "theInt", Lucene.Net.Search.FieldCache_Fields.DEFAULT_INT_PARSER);
+			strings = cache.GetStrings(readerX, "theInt");
+			
+			// this one is ok
+			bytes = cache.GetBytes(readerX, "theByte");
+			
+			// // // 
+			
+			Insanity[] insanity = FieldCacheSanityChecker.CheckSanity(cache.GetCacheEntries());
+			
+			Assert.AreEqual(1, insanity.Length, "wrong number of cache errors");
+			Assert.AreEqual(InsanityType.VALUEMISMATCH, insanity[0].GetType(), "wrong type of cache error");
+			Assert.AreEqual(2, insanity[0].GetCacheEntries().Length, "wrong number of entries in cache error");
+			
+			// we expect bad things, don't let tearDown complain about them
+			cache.PurgeAllCaches();
+		}
+		
+		[Test]
+		public virtual void  TestInsanity2()
+		{
+			FieldCache cache = Lucene.Net.Search.FieldCache_Fields.DEFAULT;
+			cache.PurgeAllCaches();
+			
+			System.String[] strings;
+			byte[] bytes;
+			
+			strings = cache.GetStrings(readerA, "theString");
+			strings = cache.GetStrings(readerB, "theString");
+			strings = cache.GetStrings(readerX, "theString");
+			
+			// this one is ok
+			bytes = cache.GetBytes(readerX, "theByte");
+			
+			
+			// // // 
+			
+			Insanity[] insanity = FieldCacheSanityChecker.CheckSanity(cache.GetCacheEntries());
+			
+			Assert.AreEqual(1, insanity.Length, "wrong number of cache errors");
+			Assert.AreEqual(InsanityType.SUBREADER, insanity[0].GetType(), "wrong type of cache error");
+			Assert.AreEqual(3, insanity[0].GetCacheEntries().Length, "wrong number of entries in cache error");
+			
+			// we expect bad things, don't let tearDown complain about them
+			cache.PurgeAllCaches();
+		}
+		
+		[Test]
+		public virtual void  TestInsanity3()
+		{
+			
+			// :TODO: subreader tree walking is really hairy ... add more crazy tests.
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Test/Util/TestIndexableBinaryStringTools.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/TestIndexableBinaryStringTools.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/TestIndexableBinaryStringTools.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/TestIndexableBinaryStringTools.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,187 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+namespace Lucene.Net.Util
+{
+	
+    [TestFixture]
+	public class TestIndexableBinaryStringTools:LuceneTestCase
+	{
+		private const int NUM_RANDOM_TESTS = 20000;
+		private const int MAX_RANDOM_BINARY_LENGTH = 300;
+		
+        [Test]
+		public virtual void  TestSingleBinaryRoundTrip()
+		{
+            System.Diagnostics.Debug.Fail("Port issue:", "byteBuf = ByteBuffer.wrap(newBuffer)"); // {{Aroush-2.9}}
+
+			//byte[] binary = new byte[]{(byte) 0x23, (byte) SupportClass.Identity(0x98), (byte) 0x13, (byte) SupportClass.Identity(0xE4), (byte) 0x76, (byte) 0x41, (byte) SupportClass.Identity(0xB2), (byte) SupportClass.Identity(0xC9), (byte) 0x7F, (byte) 0x0A, (byte) SupportClass.Identity(0xA6), (byte) SupportClass.Identity(0xD8)};
+			//
+			//System.IO.MemoryStream binaryBuf = ByteBuffer.wrap(binary);
+			//System.IO.MemoryStream encoded = IndexableBinaryStringTools.Encode(binaryBuf);
+			//ByteBuffer decoded = IndexableBinaryStringTools.Decode(encoded);
+            //Assert.AreEqual(binaryBuf, decoded, "Round trip decode/decode returned different results:" + System.Environment.NewLine + "original: " + BinaryDump(binaryBuf) + System.Environment.NewLine + " encoded: " + CharArrayDump(encoded) + System.Environment.NewLine + " decoded: " + BinaryDump(decoded));
+		}
+		
+        [Test]
+		public virtual void  TestEncodedSortability()
+		{
+			System.Random random = NewRandom();
+			byte[] originalArray1 = new byte[MAX_RANDOM_BINARY_LENGTH];
+            System.IO.MemoryStream originalBuf1 = new System.IO.MemoryStream(originalArray1);
+			byte[] originalString1 = new byte[MAX_RANDOM_BINARY_LENGTH];    // {{Aroush-2.9}} this is char[] in Java
+			System.IO.MemoryStream originalStringBuf1 = new System.IO.MemoryStream(originalString1);
+			byte[] encoded1 = new byte[IndexableBinaryStringTools.GetEncodedLength(originalBuf1)];  // {{Aroush-2.9}} this is char[] in Java
+			System.IO.MemoryStream encodedBuf1 = new System.IO.MemoryStream(encoded1);
+			byte[] original2 = new byte[MAX_RANDOM_BINARY_LENGTH];
+			System.IO.MemoryStream originalBuf2 = new System.IO.MemoryStream(original2);
+			byte[] originalString2 = new byte[MAX_RANDOM_BINARY_LENGTH];    // {{Aroush-2.9}} this is char[] in Java
+			System.IO.MemoryStream originalStringBuf2 = new System.IO.MemoryStream(originalString2);
+			byte[] encoded2 = new byte[IndexableBinaryStringTools.GetEncodedLength(originalBuf2)];  // {{Aroush-2.9}} this is char[] in Java
+			System.IO.MemoryStream encodedBuf2 = new System.IO.MemoryStream(encoded2);
+			for (int testNum = 0; testNum < NUM_RANDOM_TESTS; ++testNum)
+			{
+				int numBytes1 = random.Next(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
+				originalBuf1.Capacity = numBytes1;
+				originalStringBuf1.Capacity = numBytes1;
+				
+				for (int byteNum = 0; byteNum < numBytes1; ++byteNum)
+				{
+					int randomInt = random.Next(0x100);
+					originalArray1[byteNum] = (byte) randomInt;
+					originalString1[byteNum] = (byte) randomInt;
+				}
+				
+				int numBytes2 = random.Next(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
+				originalBuf2.Capacity = numBytes2;
+				originalStringBuf2.Capacity = numBytes2;
+				for (int byteNum = 0; byteNum < numBytes2; ++byteNum)
+				{
+					int randomInt = random.Next(0x100);
+					original2[byteNum] = (byte) randomInt;
+					originalString2[byteNum] = (byte) randomInt;
+				}
+                System.Diagnostics.Debug.Fail("Port issue:", "int originalComparison = originalStringBuf1.CompareTo(originalStringBuf2);"); // {{Aroush-2.9}}
+                int originalComparison = 0;
+				//int originalComparison = originalStringBuf1.CompareTo(originalStringBuf2);
+				//originalComparison = originalComparison < 0?- 1:(originalComparison > 0?1:0);
+				
+				IndexableBinaryStringTools.Encode(originalBuf1, encodedBuf1);
+				IndexableBinaryStringTools.Encode(originalBuf2, encodedBuf2);
+
+                System.Diagnostics.Debug.Fail("Port issue:", "int encodedComparison = encodedBuf1.CompareTo(encodedBuf2);"); // {{Aroush-2.9}}
+                int encodedComparison = 0;
+				//int encodedComparison = encodedBuf1.CompareTo(encodedBuf2);
+				//encodedComparison = encodedComparison < 0?- 1:(encodedComparison > 0?1:0);
+				
+				Assert.AreEqual(originalComparison, encodedComparison, "Test #" + (testNum + 1) + ": Original bytes and encoded chars compare differently:" + System.Environment.NewLine + " binary 1: " + BinaryDump(originalBuf1) + System.Environment.NewLine + " binary 2: " + BinaryDump(originalBuf2) + System.Environment.NewLine + "encoded 1: " + CharArrayDump(encodedBuf1) + System.Environment.NewLine + "encoded 2: " + CharArrayDump(encodedBuf2) + System.Environment.NewLine);
+			}
+		}
+		
+        [Test]
+		public virtual void  TestEmptyInput()
+		{
+			byte[] binary = new byte[0];
+            System.IO.MemoryStream encoded = IndexableBinaryStringTools.Encode((new System.IO.MemoryStream(binary)));
+			System.IO.MemoryStream decoded = IndexableBinaryStringTools.Decode(encoded);
+			Assert.IsNotNull(decoded, "decode() returned null");
+			Assert.AreEqual(decoded.Capacity, 0, "decoded empty input was not empty");
+		}
+		
+        [Test]
+		public virtual void  TestAllNullInput()
+		{
+			byte[] binary = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
+			System.IO.MemoryStream binaryBuf = new System.IO.MemoryStream(binary);
+			System.IO.MemoryStream encoded = IndexableBinaryStringTools.Encode(binaryBuf);
+			Assert.IsNotNull(encoded, "encode() returned null");
+			System.IO.MemoryStream decodedBuf = IndexableBinaryStringTools.Decode(encoded);
+			Assert.IsNotNull(decodedBuf, "decode() returned null");
+			Assert.AreEqual(binaryBuf, decodedBuf, "Round trip decode/decode returned different results:" + System.Environment.NewLine + "  original: " + BinaryDump(binaryBuf) + System.Environment.NewLine + "decodedBuf: " + BinaryDump(decodedBuf));
+		}
+		
+        [Test]
+		public virtual void  TestRandomBinaryRoundTrip()
+		{
+			System.Random random = NewRandom();
+			byte[] binary = new byte[MAX_RANDOM_BINARY_LENGTH];
+			System.IO.MemoryStream binaryBuf = new System.IO.MemoryStream(binary);
+			byte[] encoded = new byte[IndexableBinaryStringTools.GetEncodedLength(binaryBuf)];  // {{Aroush-2.9}} this is char[] in Java
+			System.IO.MemoryStream encodedBuf = new System.IO.MemoryStream(encoded);
+			byte[] decoded = new byte[MAX_RANDOM_BINARY_LENGTH];
+			System.IO.MemoryStream decodedBuf = new System.IO.MemoryStream(decoded);
+			for (int testNum = 0; testNum < NUM_RANDOM_TESTS; ++testNum)
+			{
+				int numBytes = random.Next(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
+				binaryBuf.Capacity = numBytes;
+				for (int byteNum = 0; byteNum < numBytes; ++byteNum)
+				{
+					binary[byteNum] = (byte) random.Next(0x100);
+				}
+				IndexableBinaryStringTools.Encode(binaryBuf, encodedBuf);
+				IndexableBinaryStringTools.Decode(encodedBuf, decodedBuf);
+				Assert.AreEqual(binaryBuf, decodedBuf, "Test #" + (testNum + 1) + ": Round trip decode/decode returned different results:" + System.Environment.NewLine + "  original: " + BinaryDump(binaryBuf) + System.Environment.NewLine + "encodedBuf: " + CharArrayDump(encodedBuf) + System.Environment.NewLine + "decodedBuf: " + BinaryDump(decodedBuf));
+			}
+		}
+		
+		public virtual System.String BinaryDump(System.IO.MemoryStream binaryBuf)
+		{
+			System.Text.StringBuilder buf = new System.Text.StringBuilder();
+			long numBytes = binaryBuf.Capacity - binaryBuf.Position;
+			byte[] binary = binaryBuf.ToArray();
+			for (int byteNum = 0; byteNum < numBytes; ++byteNum)
+			{
+				System.String hex = System.Convert.ToString((int) binary[byteNum] & 0xFF, 16);
+				if (hex.Length == 1)
+				{
+					buf.Append('0');
+				}
+				buf.Append(hex.ToUpper());
+				if (byteNum < numBytes - 1)
+				{
+					buf.Append(' ');
+				}
+			}
+			return buf.ToString();
+		}
+		
+		public virtual System.String CharArrayDump(System.IO.MemoryStream charBuf)
+		{
+			System.Text.StringBuilder buf = new System.Text.StringBuilder();
+			long numBytes = charBuf.Capacity - charBuf.Position;
+			byte[] charArray = charBuf.GetBuffer(); // {{Aroush-2.9}} this is char[] in Java
+			for (int charNum = 0; charNum < numBytes; ++charNum)
+			{
+				System.String hex = System.Convert.ToString((int) charArray[charNum], 16);
+				for (int digit = 0; digit < 4 - hex.Length; ++digit)
+				{
+					buf.Append('0');
+				}
+				buf.Append(hex.ToUpper());
+				if (charNum < numBytes - 1)
+				{
+					buf.Append(' ');
+				}
+			}
+			return buf.ToString();
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Test/Util/TestNumericUtils.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Test/Util/TestNumericUtils.cs?rev=832486&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Test/Util/TestNumericUtils.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Test/Util/TestNumericUtils.cs Tue Nov  3 18:06:27 2009
@@ -0,0 +1,383 @@
+/* 
+ * 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 System;
+
+using NUnit.Framework;
+
+namespace Lucene.Net.Util
+{
+	
+    [TestFixture]
+	public class TestNumericUtils:LuceneTestCase
+	{
+		private class AnonymousClassLongRangeBuilder:NumericUtils.LongRangeBuilder
+		{
+			public AnonymousClassLongRangeBuilder(long lower, long upper, bool useBitSet, Lucene.Net.Util.OpenBitSet bits, System.Collections.IEnumerator neededBounds, TestNumericUtils enclosingInstance)
+			{
+				InitBlock(lower, upper, useBitSet, bits, neededBounds, enclosingInstance);
+			}
+			private void  InitBlock(long lower, long upper, bool useBitSet, Lucene.Net.Util.OpenBitSet bits, System.Collections.IEnumerator neededBounds, TestNumericUtils enclosingInstance)
+			{
+				this.lower = lower;
+				this.upper = upper;
+				this.useBitSet = useBitSet;
+				this.bits = bits;
+				this.neededBounds = neededBounds;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private long lower;
+			private long upper;
+			private bool useBitSet;
+			private Lucene.Net.Util.OpenBitSet bits;
+			private System.Collections.IEnumerator neededBounds;
+			private TestNumericUtils enclosingInstance;
+			public TestNumericUtils Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			//@Override
+			public override void  AddRange(long min, long max, int shift)
+			{
+				Assert.IsTrue(min >= lower && min <= upper && max >= lower && max <= upper, "min, max should be inside bounds");
+				if (useBitSet)
+					for (long l = min; l <= max; l++)
+					{
+						Assert.IsFalse(bits.GetAndSet(l - lower), "ranges should not overlap");
+					}
+				// make unsigned longs for easier display and understanding
+				min ^= unchecked((int) 0x8000000000000000L);
+				max ^= unchecked((int) 0x8000000000000000L);
+				//System.out.println("new Long(0x"+Long.toHexString(min>>>shift)+"L),new Long(0x"+Long.toHexString(max>>>shift)+"L),");
+				Assert.AreEqual((long) ((System.Int64) neededBounds.Current), SupportClass.Number.URShift(min, shift), "inner min bound");
+				Assert.AreEqual((long) ((System.Int64) neededBounds.Current), SupportClass.Number.URShift(max, shift), "inner max bound");
+			}
+		}
+		private class AnonymousClassIntRangeBuilder:NumericUtils.IntRangeBuilder
+		{
+			public AnonymousClassIntRangeBuilder(int lower, int upper, bool useBitSet, Lucene.Net.Util.OpenBitSet bits, System.Collections.IEnumerator neededBounds, TestNumericUtils enclosingInstance)
+			{
+				InitBlock(lower, upper, useBitSet, bits, neededBounds, enclosingInstance);
+			}
+			private void  InitBlock(int lower, int upper, bool useBitSet, Lucene.Net.Util.OpenBitSet bits, System.Collections.IEnumerator neededBounds, TestNumericUtils enclosingInstance)
+			{
+				this.lower = lower;
+				this.upper = upper;
+				this.useBitSet = useBitSet;
+				this.bits = bits;
+				this.neededBounds = neededBounds;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private int lower;
+			private int upper;
+			private bool useBitSet;
+			private Lucene.Net.Util.OpenBitSet bits;
+			private System.Collections.IEnumerator neededBounds;
+			private TestNumericUtils enclosingInstance;
+			public TestNumericUtils Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			//@Override
+			public override void  AddRange(int min, int max, int shift)
+			{
+				Assert.IsTrue(min >= lower && min <= upper && max >= lower && max <= upper, "min, max should be inside bounds");
+				if (useBitSet)
+					for (int i = min; i <= max; i++)
+					{
+						Assert.IsFalse(bits.GetAndSet(i - lower), "ranges should not overlap");
+					}
+				// make unsigned ints for easier display and understanding
+				min ^= unchecked((int) 0x80000000);
+				max ^= unchecked((int) 0x80000000);
+				//System.out.println("new Integer(0x"+Integer.toHexString(min>>>shift)+"),new Integer(0x"+Integer.toHexString(max>>>shift)+"),");
+				Assert.AreEqual(((System.Int32) neededBounds.Current), SupportClass.Number.URShift(min, shift), "inner min bound");
+				Assert.AreEqual(((System.Int32) neededBounds.Current), SupportClass.Number.URShift(max, shift), "inner max bound");
+			}
+		}
+		
+        [Test]
+		public virtual void  TestLongConversionAndOrdering()
+		{
+			// generate a series of encoded longs, each numerical one bigger than the one before
+			System.String last = null;
+			for (long l = - 100000L; l < 100000L; l++)
+			{
+				System.String act = NumericUtils.LongToPrefixCoded(l);
+				if (last != null)
+				{
+					// test if smaller
+					Assert.IsTrue(String.CompareOrdinal(last, act) < 0, "actual bigger than last");
+				}
+				// test is back and forward conversion works
+				Assert.AreEqual(l, NumericUtils.PrefixCodedToLong(act), "forward and back conversion should generate same long");
+				// next step
+				last = act;
+			}
+		}
+		
+        [Test]
+		public virtual void  TestIntConversionAndOrdering()
+		{
+			// generate a series of encoded ints, each numerical one bigger than the one before
+			System.String last = null;
+			for (int i = - 100000; i < 100000; i++)
+			{
+				System.String act = NumericUtils.IntToPrefixCoded(i);
+				if (last != null)
+				{
+					// test if smaller
+					Assert.IsTrue(String.CompareOrdinal(last, act) < 0, "actual bigger than last");
+				}
+				// test is back and forward conversion works
+				Assert.AreEqual(i, NumericUtils.PrefixCodedToInt(act), "forward and back conversion should generate same int");
+				// next step
+				last = act;
+			}
+		}
+		
+        [Test]
+		public virtual void  TestLongSpecialValues()
+		{
+			long[] vals = new long[]{System.Int64.MinValue, System.Int64.MinValue + 1, System.Int64.MinValue + 2, - 5003400000000L, - 4000L, - 3000L, - 2000L, - 1000L, - 1L, 0L, 1L, 10L, 300L, 50006789999999999L, System.Int64.MaxValue - 2, System.Int64.MaxValue - 1, System.Int64.MaxValue};
+			System.String[] prefixVals = new System.String[vals.Length];
+			
+			for (int i = 0; i < vals.Length; i++)
+			{
+				prefixVals[i] = NumericUtils.LongToPrefixCoded(vals[i]);
+				
+				// check forward and back conversion
+				Assert.AreEqual(vals[i], NumericUtils.PrefixCodedToLong(prefixVals[i]), "forward and back conversion should generate same long");
+				
+				// test if decoding values as int fails correctly
+				try
+				{
+					NumericUtils.PrefixCodedToInt(prefixVals[i]);
+					Assert.Fail("decoding a prefix coded long value as int should fail");
+				}
+				catch (System.FormatException e)
+				{
+					// worked
+				}
+			}
+			
+			// check sort order (prefixVals should be ascending)
+			for (int i = 1; i < prefixVals.Length; i++)
+			{
+				Assert.IsTrue(String.CompareOrdinal(prefixVals[i - 1], prefixVals[i]) < 0, "check sort order");
+			}
+			
+			// check the prefix encoding, lower precision should have the difference to original value equal to the lower removed bits
+			for (int i = 0; i < vals.Length; i++)
+			{
+				for (int j = 0; j < 64; j++)
+				{
+					long prefixVal = NumericUtils.PrefixCodedToLong(NumericUtils.LongToPrefixCoded(vals[i], j));
+					long mask = (1L << j) - 1L;
+					Assert.AreEqual(vals[i] & mask, vals[i] - prefixVal, "difference between prefix val and original value for " + vals[i] + " with shift=" + j);
+				}
+			}
+		}
+		
+        [Test]
+		public virtual void  TestIntSpecialValues()
+		{
+			int[] vals = new int[]{System.Int32.MinValue, System.Int32.MinValue + 1, System.Int32.MinValue + 2, - 64765767, - 4000, - 3000, - 2000, - 1000, - 1, 0, 1, 10, 300, 765878989, System.Int32.MaxValue - 2, System.Int32.MaxValue - 1, System.Int32.MaxValue};
+			System.String[] prefixVals = new System.String[vals.Length];
+			
+			for (int i = 0; i < vals.Length; i++)
+			{
+				prefixVals[i] = NumericUtils.IntToPrefixCoded(vals[i]);
+				
+				// check forward and back conversion
+				Assert.AreEqual(vals[i], NumericUtils.PrefixCodedToInt(prefixVals[i]), "forward and back conversion should generate same int");
+				
+				// test if decoding values as long fails correctly
+				try
+				{
+					NumericUtils.PrefixCodedToLong(prefixVals[i]);
+					Assert.Fail("decoding a prefix coded int value as long should fail");
+				}
+				catch (System.FormatException e)
+				{
+					// worked
+				}
+			}
+			
+			// check sort order (prefixVals should be ascending)
+			for (int i = 1; i < prefixVals.Length; i++)
+			{
+				Assert.IsTrue(String.CompareOrdinal(prefixVals[i - 1], prefixVals[i]) < 0, "check sort order");
+			}
+			
+			// check the prefix encoding, lower precision should have the difference to original value equal to the lower removed bits
+			for (int i = 0; i < vals.Length; i++)
+			{
+				for (int j = 0; j < 32; j++)
+				{
+					int prefixVal = NumericUtils.PrefixCodedToInt(NumericUtils.IntToPrefixCoded(vals[i], j));
+					int mask = (1 << j) - 1;
+					Assert.AreEqual(vals[i] & mask, vals[i] - prefixVal, "difference between prefix val and original value for " + vals[i] + " with shift=" + j);
+				}
+			}
+		}
+		
+        [Test]
+		public virtual void  TestDoubles()
+		{
+			double[] vals = new double[]{System.Double.NegativeInfinity, - 2.3e25, - 1.0e15, - 1.0, - 1.0e-1, - 1.0e-2, - 0.0, + 0.0, 1.0e-2, 1.0e-1, 1.0, 1.0e15, 2.3e25, System.Double.PositiveInfinity};
+			long[] longVals = new long[vals.Length];
+			
+			// check forward and back conversion
+			for (int i = 0; i < vals.Length; i++)
+			{
+				longVals[i] = NumericUtils.DoubleToSortableLong(vals[i]);
+				Assert.IsTrue(BitConverter.Int64BitsToDouble((long) vals[i]) == NumericUtils.SortableLongToDouble(longVals[i]), "forward and back conversion should generate same double");
+			}
+			
+			// check sort order (prefixVals should be ascending)
+			for (int i = 1; i < longVals.Length; i++)
+			{
+				Assert.IsTrue(longVals[i - 1] < longVals[i], "check sort order");
+			}
+		}
+		
+        [Test]
+		public virtual void  TestFloats()
+		{
+			float[] vals = new float[]{System.Single.NegativeInfinity, - 2.3e25f, - 1.0e15f, - 1.0f, - 1.0e-1f, - 1.0e-2f, - 0.0f, + 0.0f, 1.0e-2f, 1.0e-1f, 1.0f, 1.0e15f, 2.3e25f, System.Single.PositiveInfinity};
+			int[] intVals = new int[vals.Length];
+			
+			// check forward and back conversion
+			for (int i = 0; i < vals.Length; i++)
+			{
+				intVals[i] = NumericUtils.FloatToSortableInt(vals[i]);
+				Assert.IsTrue(BitConverter.ToSingle(BitConverter.GetBytes(vals[i]), 0) == NumericUtils.SortableIntToFloat(intVals[i]), "forward and back conversion should generate same double");
+			}
+			
+			// check sort order (prefixVals should be ascending)
+			for (int i = 1; i < intVals.Length; i++)
+			{
+				Assert.IsTrue(intVals[i - 1] < intVals[i], "check sort order");
+			}
+		}
+		
+		// INFO: Tests for trieCodeLong()/trieCodeInt() not needed because implicitely tested by range filter tests
+		
+		/// <summary>Note: The neededBounds iterator must be unsigned (easier understanding what's happening) </summary>
+		protected internal virtual void  AssertLongRangeSplit(long lower, long upper, int precisionStep, bool useBitSet, System.Collections.IEnumerator neededBounds)
+		{
+			OpenBitSet bits = useBitSet?new OpenBitSet(upper - lower + 1):null;
+			
+			NumericUtils.SplitLongRange(new AnonymousClassLongRangeBuilder(lower, upper, useBitSet, bits, neededBounds, this), precisionStep, lower, upper);
+			
+			if (useBitSet)
+			{
+				// after flipping all bits in the range, the cardinality should be zero
+				bits.Flip(0, upper - lower + 1);
+				Assert.IsTrue(bits.IsEmpty(), "The sub-range concenated should match the whole range");
+			}
+		}
+		
+        [Test]
+		public virtual void  TestSplitLongRange()
+		{
+			// a hard-coded "standard" range
+			AssertLongRangeSplit(- 5000L, 9500L, 4, true, new System.Collections.ArrayList(new System.Int64[]{0x7fffffffffffec78L, 0x7fffffffffffec7fL, unchecked((long) (0x8000000000002510L)), unchecked((long) (0x800000000000251cL)), 0x7fffffffffffec8L, 0x7fffffffffffecfL, 0x800000000000250L, 0x800000000000250L, 0x7fffffffffffedL, 0x7fffffffffffefL, 0x80000000000020L, 0x80000000000024L, 0x7ffffffffffffL, 0x8000000000001L}).GetEnumerator());
+			
+			// the same with no range splitting
+			AssertLongRangeSplit(- 5000L, 9500L, 64, true, new System.Collections.ArrayList(new System.Int64[]{0x7fffffffffffec78L, unchecked((long) (0x800000000000251cL))}).GetEnumerator());
+			
+			// this tests optimized range splitting, if one of the inner bounds
+			// is also the bound of the next lower precision, it should be used completely
+			AssertLongRangeSplit(0L, 1024L + 63L, 4, true, new System.Collections.ArrayList(new System.Int64[]{0x800000000000040L, 0x800000000000043L, 0x80000000000000L, 0x80000000000003L}).GetEnumerator());
+			
+			// the full long range should only consist of a lowest precision range; no bitset testing here, as too much memory needed :-)
+			AssertLongRangeSplit(System.Int64.MinValue, System.Int64.MaxValue, 8, false, new System.Collections.ArrayList(new System.Int64[]{0x00L, 0xffL}).GetEnumerator());
+			
+			// the same with precisionStep=4
+			AssertLongRangeSplit(System.Int64.MinValue, System.Int64.MaxValue, 4, false, new System.Collections.ArrayList(new System.Int64[]{0x0L, 0xfL}).GetEnumerator());
+			
+			// the same with precisionStep=2
+			AssertLongRangeSplit(System.Int64.MinValue, System.Int64.MaxValue, 2, false, new System.Collections.ArrayList(new System.Int64[]{0x0L, 0x3L}).GetEnumerator());
+			
+			// the same with precisionStep=1
+			AssertLongRangeSplit(System.Int64.MinValue, System.Int64.MaxValue, 1, false, new System.Collections.ArrayList(new System.Int64[]{0x0L, 0x1L}).GetEnumerator());
+			
+			// a inverse range should produce no sub-ranges
+			AssertLongRangeSplit(9500L, - 5000L, 4, false, ((System.Collections.IList) System.Collections.ArrayList.ReadOnly(new System.Collections.ArrayList())).GetEnumerator());
+			
+			// a 0-length range should reproduce the range itsself
+			AssertLongRangeSplit(9500L, 9500L, 4, false, new System.Collections.ArrayList(new System.Int64[]{unchecked((long) (0x800000000000251cL)), unchecked((long) (0x800000000000251cL))}).GetEnumerator());
+		}
+		
+		/// <summary>Note: The neededBounds iterator must be unsigned (easier understanding what's happening) </summary>
+		protected internal virtual void  AssertIntRangeSplit(int lower, int upper, int precisionStep, bool useBitSet, System.Collections.IEnumerator neededBounds)
+		{
+			OpenBitSet bits = useBitSet?new OpenBitSet(upper - lower + 1):null;
+			
+			NumericUtils.SplitIntRange(new AnonymousClassIntRangeBuilder(lower, upper, useBitSet, bits, neededBounds, this), precisionStep, lower, upper);
+			
+			if (useBitSet)
+			{
+				// after flipping all bits in the range, the cardinality should be zero
+				bits.Flip(0, upper - lower + 1);
+				Assert.IsTrue(bits.IsEmpty(), "The sub-range concenated should match the whole range");
+			}
+		}
+		
+        [Test]
+		public virtual void  TestSplitIntRange()
+		{
+			// a hard-coded "standard" range
+			AssertIntRangeSplit(- 5000, 9500, 4, true, new System.Collections.ArrayList(new System.Int32[]{0x7fffec78, 0x7fffec7f, unchecked((System.Int32) 0x80002510), unchecked((System.Int32) 0x8000251c), 0x7fffec8, 0x7fffecf, 0x8000250, 0x8000250, 0x7fffed, 0x7fffef, 0x800020, 0x800024, 0x7ffff, 0x80001}).GetEnumerator());
+			
+			// the same with no range splitting
+			AssertIntRangeSplit(- 5000, 9500, 32, true, new System.Collections.ArrayList(new System.Int32[]{0x7fffec78, unchecked((System.Int32) 0x8000251c)}).GetEnumerator());
+			
+			// this tests optimized range splitting, if one of the inner bounds
+			// is also the bound of the next lower precision, it should be used completely
+			AssertIntRangeSplit(0, 1024 + 63, 4, true, new System.Collections.ArrayList(new System.Int32[]{0x8000040, 0x8000043, 0x800000, 0x800003}).GetEnumerator());
+			
+			// the full int range should only consist of a lowest precision range; no bitset testing here, as too much memory needed :-)
+			AssertIntRangeSplit(System.Int32.MinValue, System.Int32.MaxValue, 8, false, new System.Collections.ArrayList(new System.Int32[]{0x00, 0xff}).GetEnumerator());
+			
+			// the same with precisionStep=4
+			AssertIntRangeSplit(System.Int32.MinValue, System.Int32.MaxValue, 4, false, new System.Collections.ArrayList(new System.Int32[]{0x0, 0xf}).GetEnumerator());
+			
+			// the same with precisionStep=2
+			AssertIntRangeSplit(System.Int32.MinValue, System.Int32.MaxValue, 2, false, new System.Collections.ArrayList(new System.Int32[]{0x0, 0x3}).GetEnumerator());
+			
+			// the same with precisionStep=1
+			AssertIntRangeSplit(System.Int32.MinValue, System.Int32.MaxValue, 1, false, new System.Collections.ArrayList(new System.Int32[]{0x0, 0x1}).GetEnumerator());
+			
+			// a inverse range should produce no sub-ranges
+			AssertIntRangeSplit(9500, - 5000, 4, false, ((System.Collections.IList) System.Collections.ArrayList.ReadOnly(new System.Collections.ArrayList())).GetEnumerator());
+			
+			// a 0-length range should reproduce the range itsself
+			AssertIntRangeSplit(9500, 9500, 4, false, new System.Collections.ArrayList(new System.Int32[]{unchecked((System.Int32) 0x8000251c), unchecked((System.Int32) 0x8000251c)}).GetEnumerator());
+		}
+	}
+}
\ No newline at end of file