blob: fde368dcc3d59b01e15d6d05395d687616792bc8 [file] [log] [blame]
// LUCENENET specific - factored out this WeakIdentityMap<TKey, TValue> and replaced it with ConditionalWeakTable<TKey, TValue>.
// ConditionalWeakTable<TKey, TValue> is thread-safe and internally uses RuntimeHelpers.GetHashCode()
// to lookup the key, so it can be used as a direct replacement for WeakIdentityMap<TKey, TValue>
// in most cases.
//using J2N.Threading;
//using J2N.Threading.Atomic;
//using Lucene.Net.Attributes;
//using NUnit.Framework;
//using System;
//using System.Collections.Generic;
//using System.Globalization;
//using System.Threading;
//using Assert = Lucene.Net.TestFramework.Assert;
//namespace Lucene.Net.Util
//{
// /*
// * Licensed to the Apache Software Foundation (ASF) under one or more
// * contributor license agreements. See the NOTICE file distributed with
// * this work for additional information regarding copyright ownership.
// * The ASF licenses this file to You under the Apache License, Version 2.0
// * (the "License"); you may not use this file except in compliance with
// * the License. You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
// [TestFixture]
// public class TestWeakIdentityMap : LuceneTestCase
// {
// [Test, Slow]
// public virtual void TestSimpleHashMap()
// {
// WeakIdentityMap<string, string> map = WeakIdentityMap<string, string>.NewHashMap(Random.NextBoolean());
// // we keep strong references to the keys,
// // so WeakIdentityMap will not forget about them:
// string key1 = "foo";
// string key2 = "test1 foo".Split(' ')[1];
// string key3 = "test2 foo".Split(' ')[1];
// // LUCENENET NOTE: As per http://stackoverflow.com/a/543329/181087,
// // the above hack is required in order to ensure the AreNotSame
// // check will work. If you assign the same string to 3 different variables
// // without doing some kind of manipulation from the original string, the
// // AreNotSame test will fail because the references will be the same.
// Assert.AreNotSame(key1, key2);
// Assert.AreEqual(key1, key2);
// Assert.AreNotSame(key1, key3);
// Assert.AreEqual(key1, key3);
// Assert.AreNotSame(key2, key3);
// Assert.AreEqual(key2, key3);
// // try null key & check its iterator also return null:
// map.Put(null, "null");
// {
// using (IEnumerator<string> iter = map.Keys.GetEnumerator())
// {
// Assert.IsTrue(iter.MoveNext());
// Assert.IsNull(iter.Current);
// Assert.IsFalse(iter.MoveNext());
// Assert.IsFalse(iter.MoveNext());
// }
// }
// // 2 more keys:
// map.Put(key1, "bar1");
// map.Put(key2, "bar2");
// Assert.AreEqual(3, map.Count);
// Assert.AreEqual("bar1", map.Get(key1));
// Assert.AreEqual("bar2", map.Get(key2));
// Assert.AreEqual(null, map.Get(key3));
// Assert.AreEqual("null", map.Get(null));
// Assert.IsTrue(map.ContainsKey(key1));
// Assert.IsTrue(map.ContainsKey(key2));
// Assert.IsFalse(map.ContainsKey(key3));
// Assert.IsTrue(map.ContainsKey(null));
// // repeat and check that we have no double entries
// map.Put(key1, "bar1");
// map.Put(key2, "bar2");
// map.Put(null, "null");
// Assert.AreEqual(3, map.Count);
// Assert.AreEqual("bar1", map.Get(key1));
// Assert.AreEqual("bar2", map.Get(key2));
// Assert.AreEqual(null, map.Get(key3));
// Assert.AreEqual("null", map.Get(null));
// Assert.IsTrue(map.ContainsKey(key1));
// Assert.IsTrue(map.ContainsKey(key2));
// Assert.IsFalse(map.ContainsKey(key3));
// Assert.IsTrue(map.ContainsKey(null));
// map.Remove(null);
// Assert.AreEqual(2, map.Count);
// map.Remove(key1);
// Assert.AreEqual(1, map.Count);
// map.Put(key1, "bar1");
// map.Put(key2, "bar2");
// map.Put(key3, "bar3");
// Assert.AreEqual(3, map.Count);
// int c = 0, keysAssigned = 0;
// foreach (object k in map.Keys)
// {
// //Assert.IsTrue(iter.hasNext()); // try again, should return same result!
// // LUCENENET NOTE: Need object.ReferenceEquals here because the == operator does more than check reference equality
// Assert.IsTrue(object.ReferenceEquals(k, key1) || object.ReferenceEquals(k, key2) | object.ReferenceEquals(k, key3));
// keysAssigned += object.ReferenceEquals(k, key1) ? 1 : (object.ReferenceEquals(k, key2) ? 2 : 4);
// c++;
// }
// Assert.AreEqual(3, c);
// Assert.AreEqual(1 + 2 + 4, keysAssigned, "all keys must have been seen");
// c = 0;
// for (IEnumerator<string> iter = map.Values.GetEnumerator(); iter.MoveNext();)
// {
// string v = iter.Current;
// Assert.IsTrue(v.StartsWith("bar", StringComparison.Ordinal));
// c++;
// }
// Assert.AreEqual(3, c);
// // clear strong refs
// key1 = key2 = key3 = null;
// // check that GC does not cause problems in reap() method, wait 1 second and let GC work:
// int size = map.Count;
// for (int i = 0; size > 0 && i < 10; i++)
// {
//#if FEATURE_THREAD_INTERRUPT
// try
// {
//#endif
// GC.Collect();
// int newSize = map.Count;
// Assert.IsTrue(size >= newSize, "previousSize(" + size + ")>=newSize(" + newSize + ")");
// size = newSize;
// Thread.Sleep(TimeSpan.FromSeconds(1));
// c = 0;
// foreach (object k in map.Keys)
// {
// Assert.IsNotNull(k);
// c++;
// }
// newSize = map.Count;
// Assert.IsTrue(size >= c, "previousSize(" + size + ")>=iteratorSize(" + c + ")");
// Assert.IsTrue(c >= newSize, "iteratorSize(" + c + ")>=newSize(" + newSize + ")");
// size = newSize;
//#if FEATURE_THREAD_INTERRUPT
// }
//#pragma warning disable 168
// catch (ThreadInterruptedException ie)
//#pragma warning restore 168
// {
// }
//#endif
// }
// map.Clear();
// Assert.AreEqual(0, map.Count);
// Assert.IsTrue(map.IsEmpty);
// using (IEnumerator<string> it = map.Keys.GetEnumerator())
// Assert.IsFalse(it.MoveNext());
// /*try
// {
// it.Next();
// Assert.Fail("Should throw NoSuchElementException");
// }
// catch (NoSuchElementException nse)
// {
// }*/
// // LUCENENET NOTE: As per http://stackoverflow.com/a/543329/181087,
// // the following hack is required in order to ensure the string references
// // are different. If you assign the same string to 2 different variables
// // without doing some kind of manipulation from the original string, the
// // references will be the same.
// key1 = "test3 foo".Split(' ')[1];
// key2 = "test4 foo".Split(' ')[1];
// map.Put(key1, "bar1");
// map.Put(key2, "bar2");
// Assert.AreEqual(2, map.Count);
// map.Clear();
// Assert.AreEqual(0, map.Count);
// Assert.IsTrue(map.IsEmpty);
// }
// [Test, Slow]
// public virtual void TestConcurrentHashMap()
// {
// // don't make threadCount and keyCount random, otherwise easily OOMs or fails otherwise:
// const int threadCount = 8, keyCount = 1024;
// RunnableAnonymousClass[] workers = new RunnableAnonymousClass[threadCount];
// WeakIdentityMap<object, int?> map = WeakIdentityMap<object, int?>.NewConcurrentHashMap(Random.NextBoolean());
// // we keep strong references to the keys,
// // so WeakIdentityMap will not forget about them:
// AtomicReferenceArray<object> keys = new AtomicReferenceArray<object>(keyCount);
// for (int j = 0; j < keyCount; j++)
// {
// keys[j] = new object();
// }
// try
// {
// for (int t = 0; t < threadCount; t++)
// {
// Random rnd = new Random(Random.Next());
// var worker = new RunnableAnonymousClass(this, keyCount, map, keys, rnd);
// workers[t] = worker;
// worker.Start();
// }
// }
// finally
// {
// foreach (var w in workers)
// {
// w.Join();
// }
// }
// // LUCENENET: Since assertions were done on the other threads, we need to check the
// // results here.
// for (int i = 0; i < workers.Length; i++)
// {
// assertTrue(string.Format(CultureInfo.InvariantCulture,
// "worker thread {0} of {1} failed \n" + workers[i].Error, i, workers.Length),
// workers[i].Error == null);
// }
// // clear strong refs
// for (int j = 0; j < keyCount; j++)
// {
// keys[j] = null;
// }
// // check that GC does not cause problems in reap() method:
// int size = map.Count;
// for (int i = 0; size > 0 && i < 10; i++)
// {
//#if FEATURE_THREAD_INTERRUPT
// try
// {
//#endif
// GC.Collect();
// int newSize = map.Count;
// Assert.IsTrue(size >= newSize, "previousSize(" + size + ")>=newSize(" + newSize + ")");
// size = newSize;
// Thread.Sleep(new TimeSpan(100L));
// int c = 0;
// foreach (object k in map.Keys)
// {
// Assert.IsNotNull(k);
// c++;
// }
// newSize = map.Count;
// Assert.IsTrue(size >= c, "previousSize(" + size + ")>=iteratorSize(" + c + ")");
// Assert.IsTrue(c >= newSize, "iteratorSize(" + c + ")>=newSize(" + newSize + ")");
// size = newSize;
//#if FEATURE_THREAD_INTERRUPT
// }
//#pragma warning disable 168
// catch (ThreadInterruptedException ie)
//#pragma warning restore 168
// {
// }
//#endif
// }
// }
// private class RunnableAnonymousClass : ThreadJob
// {
// private readonly TestWeakIdentityMap outerInstance;
// private readonly int keyCount;
// private readonly WeakIdentityMap<object, int?> map;
// private AtomicReferenceArray<object> keys;
// private readonly Random rnd;
// private volatile Exception error;
// public RunnableAnonymousClass(TestWeakIdentityMap outerInstance, int keyCount, WeakIdentityMap<object, int?> map, AtomicReferenceArray<object> keys, Random rnd)
// {
// this.outerInstance = outerInstance;
// this.keyCount = keyCount;
// this.map = map;
// this.keys = keys;
// this.rnd = rnd;
// }
// public Exception Error
// {
// get { return error; }
// }
// public override void Run()
// {
// int count = AtLeast(rnd, 10000);
// try
// {
// for (int i = 0; i < count; i++)
// {
// int j = rnd.Next(keyCount);
// switch (rnd.Next(5))
// {
// case 0:
// map.Put(keys[j], Convert.ToInt32(j));
// break;
// case 1:
// int? v = map.Get(keys[j]);
// if (v != null)
// {
// Assert.AreEqual(j, (int)v);
// }
// break;
// case 2:
// map.Remove(keys[j]);
// break;
// case 3:
// // renew key, the old one will be GCed at some time:
// keys[j] = new object();
// break;
// case 4:
// // check iterator still working
// foreach (object k in map.Keys)
// {
// Assert.IsNotNull(k);
// }
// break;
// default:
// Assert.Fail("Should not get here.");
// break;
// }
// }
// }
// catch (Exception e)
// {
// e.printStackTrace();
// this.error = e;
// }
// }
// }
// }
//}