blob: 515746635aa5c6081e44d7265e028afccfafc54f [file] [log] [blame]
using Lucene.Net.Attributes;
using Lucene.Net.Util;
using NUnit.Framework;
using System;
using System.Collections;
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.
*/
public class TestEquatableSet : LuceneTestCase
{
/// <summary>
/// This test shows that System.Collections.Generic.HashSet is not suitable for determining uniqueness
/// when used in a HashSet. This is a difference between the Java and .NET BCL Lists. Since the equatable
/// behaviour of java.util.HashSet.hashCode() in Java is relied upon for the the Java Lucene implementation,
/// a correct port must use an equatable list with the same behaviour.
///
/// We include this unit test here, to prove the problem with the .NET List type. If this test fails, we
/// can remove the SupportClass.EquatableList class, and replace it with System.Collection.Generic.List.
/// </summary>
[Test, LuceneNetSpecific]
public void System_Collections_Generic_HashSet_Not_Suitable_For_Determining_Uniqueness_In_HashSet()
{
// reference equality
var foo = new Object();
var bar = new Object();
var list1 = new HashSet<Object> { foo, bar };
var list2 = new HashSet<Object> { foo, bar };
var hashSet = new HashSet<HashSet<Object>>();
Assert.IsTrue(hashSet.Add(list1));
// note: compare this assertion to the assertion in Suitable_For_Determining_Uniqueness_In_HashSet
Assert.IsTrue(hashSet.Add(list2),
"BCL List changed equality behaviour and is now suitable for use in HashSet! Yay!");
}
/// <summary>
/// This test shows that System.Collections.Generic.List is not suitable for determining uniqueness
/// when used in a Hashtable. This is a difference between the Java and .NET BCL Lists. Since the equatable
/// behaviour of java.util.List.hashCode() in Java is relied upon for the the Java Lucene implementation,
/// a correct port must use an equatable list with the same behaviour.
///
/// We include this unit test here, to prove the problem with the .NET List type. If this test fails, we
/// can remove the SupportClass.EquatableList class, and replace it with System.Collection.Generic.List.
/// </summary>
[Test, LuceneNetSpecific]
public void System_Collections_Generic_HashSet_Not_Suitable_For_Determining_Uniqueness_In_Hashtable()
{
// reference equality
var foo = new Object();
var bar = new Object();
var list1 = new HashSet<Object> { foo, bar };
var list2 = new HashSet<Object> { foo, bar };
var hashTable = new Hashtable();
Assert.IsFalse(hashTable.ContainsKey(list1));
hashTable.Add(list1, list1);
// note: compare this assertion to the assertion in Suitable_For_Determining_Uniqueness_In_Hashtable
Assert.IsFalse(
hashTable.ContainsKey(list2),
"BCL List changed behaviour and is now suitable for use as a replacement for Java's List! Yay!");
}
/// <summary>
/// There is a interesting problem with .NET's String.GetHashCode() for certain strings.
/// This unit test displays the problem, and in the event that this is changed in the
/// .NET runtime, the test will fail.
///
/// This is one of the reasons that the EquatableList implementation does not use GetHashCode()
/// (which is a divergence from the List.equals implementation in Java). EquatableList should have
/// the same overall results as Java's List however.
///
/// For an explanation of this issue see:
/// http://blogs.msdn.com/b/ericlippert/archive/2011/07/12/what-curious-property-does-this-string-have.aspx
/// For a description of the GetHashCode implementation see:
/// http://www.dotnetperls.com/gethashcode
/// For documentation on List.getHashCode(), see:
/// http://download.oracle.com/javase/6/docs/api/java/util/List.html#hashCode()
/// And in the general case, see:
/// http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()
/// </summary>
[Test, LuceneNetSpecific]
public void System_String_GetHashCode_Exhibits_Inconsistent_Inequality_For_Some_Values()
{
var val1 = "\uA0A2\uA0A2";
var val2 = string.Empty;
Assert.IsFalse(val1.Equals(val2, StringComparison.Ordinal));
var hash1 = val1.GetHashCode();
var hash2 = val2.GetHashCode();
// note: this is counter-intuative, but technically allowed by the contract for GetHashCode()
// this only works in 32 bit processes.
// if 32 bit process
if (IntPtr.Size == 4)
{
// TODO: determine if there is an similar issue when in a 64 bit process.
Assert.IsTrue(
hash1.Equals(hash2),
"BCL string.GetHashCode() no longer exhibits inconsistent inequality for certain strings."
);
}
}
[Test, LuceneNetSpecific]
public void Suitable_For_Determining_Uniqueness_In_HashSet()
{
var foo = new Object();
var bar = new Object();
var list1 = new EquatableSet<Object> { foo, bar };
var list2 = new EquatableSet<Object> { foo, bar };
Assert.AreEqual(list1, list2);
var hashSet = new HashSet<ISet<Object>>();
Assert.IsTrue(hashSet.Add(list1));
Assert.IsFalse(hashSet.Add(list2));
}
[Test, LuceneNetSpecific]
public void Suitable_For_Determining_Uniqueness_In_Hashtable()
{
var foo = new Object();
var bar = new Object();
var list1 = new EquatableSet<Object> { foo, bar };
var list2 = new EquatableSet<Object> { foo, bar };
var hashTable = new Hashtable();
Assert.IsFalse(hashTable.ContainsKey(list1));
hashTable.Add(list1, list1);
Assert.IsTrue(hashTable.ContainsKey(list2));
}
}
}