Skip to content

Commit

Permalink
Lucene.Net.Support.Threading.ReentrantLock: Changed the implementatio…
Browse files Browse the repository at this point in the history
…n to use unfair locking similar to how it was done in Java. We track the queue and use ManualResetEventSlim to control entry into the lock for queued tasks. Ported some of the ReentrantLock tests from Apache Harmony.
  • Loading branch information
NightOwl888 committed May 23, 2024
1 parent 8423edc commit 89b01e6
Show file tree
Hide file tree
Showing 5 changed files with 2,286 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .build/dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
<MicrosoftExtensionsConfigurationXmlPackageVersion>$(MicrosoftExtensionsConfigurationPackageVersion)</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.0.0</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>$(MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion)</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsObjectPoolPackageVersion>6.0.30</MicrosoftExtensionsObjectPoolPackageVersion>
<MicrosoftExtensionsObjectPoolPackageVersion Condition="$(TargetFramework.StartsWith('net8.'))">8.0.5</MicrosoftExtensionsObjectPoolPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.0.0</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftNETFrameworkReferenceAssembliesPackageReferenceVersion>1.0.2</MicrosoftNETFrameworkReferenceAssembliesPackageReferenceVersion>
<MicrosoftNETTestSdkPackageVersion>17.9.0</MicrosoftNETTestSdkPackageVersion>
Expand Down
369 changes: 369 additions & 0 deletions src/Lucene.Net.Tests/Support/Threading/JSR166TestCase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,369 @@
using Lucene.Net.Util;
using System;

namespace Lucene.Net.Support.Threading
{
/*
* 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.
*/

/**
* Base class for JSR166 Junit TCK tests. Defines some constants,
* utility methods and classes, as well as a simple framework for
* helping to make sure that assertions failing in generated threads
* cause the associated test that generated them to itself fail (which
* JUnit does not otherwise arrange). The rules for creating such
* tests are:
*
* <ol>
*
* <li> All assertions in code running in generated threads must use
* the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link
* #threadAssertEquals}, or {@link #threadAssertNull}, (not
* <tt>fail</tt>, <tt>assertTrue</tt>, etc.) It is OK (but not
* particularly recommended) for other code to use these forms too.
* Only the most typically used JUnit assertion methods are defined
* this way, but enough to live with.</li>
*
* <li> If you override {@link #setUp} or {@link #tearDown}, make sure
* to invoke <tt>super.setUp</tt> and <tt>super.tearDown</tt> within
* them. These methods are used to clear and check for thread
* assertion failures.</li>
*
* <li>All delays and timeouts must use one of the constants <tt>
* SHORT_DELAY_MS</tt>, <tt> SMALL_DELAY_MS</tt>, <tt> MEDIUM_DELAY_MS</tt>,
* <tt> LONG_DELAY_MS</tt>. The idea here is that a SHORT is always
* discriminable from zero time, and always allows enough time for the
* small amounts of computation (creating a thread, calling a few
* methods, etc) needed to reach a timeout point. Similarly, a SMALL
* is always discriminable as larger than SHORT and smaller than
* MEDIUM. And so on. These constants are set to conservative values,
* but even so, if there is ever any doubt, they can all be increased
* in one spot to rerun tests on slower platforms.</li>
*
* <li> All threads generated must be joined inside each test case
* method (or <tt>fail</tt> to do so) before returning from the
* method. The <tt> joinPool</tt> method can be used to do this when
* using Executors.</li>
*
* </ol>
*
* <p> <b>Other notes</b>
* <ul>
*
* <li> Usually, there is one testcase method per JSR166 method
* covering "normal" operation, and then as many exception-testing
* methods as there are exceptions the method can throw. Sometimes
* there are multiple tests per JSR166 method when the different
* "normal" behaviors differ significantly. And sometimes testcases
* cover multiple methods when they cannot be tested in
* isolation.</li>
*
* <li> The documentation style for testcases is to provide as javadoc
* a simple sentence or two describing the property that the testcase
* method purports to test. The javadocs do not say anything about how
* the property is tested. To find out, read the code.</li>
*
* <li> These tests are "conformance tests", and do not attempt to
* test throughput, latency, scalability or other performance factors
* (see the separate "jtreg" tests for a set intended to check these
* for the most central aspects of functionality.) So, most tests use
* the smallest sensible numbers of threads, collection sizes, etc
* needed to check basic conformance.</li>
*
* <li>The test classes currently do not declare inclusion in
* any particular package to simplify things for people integrating
* them in TCK test suites.</li>
*
* <li> As a convenience, the <tt>main</tt> of this class (JSR166TestCase)
* runs all JSR166 unit tests.</li>
*
* </ul>
*/
public class JSR166TestCase : LuceneTestCase
{
///**
// * Runs all JSR166 unit tests using junit.textui.TestRunner
// */
//public static void main(String[] args)
//{
// int iters = 1;
// if (args.length > 0)
// iters = Integer.parseInt(args[0]);
// Test s = suite();
// for (int i = 0; i < iters; ++i)
// {
// junit.textui.TestRunner.run(s);
// System.gc();
// System.runFinalization();
// }
// System.exit(0);
//}

///**
// * Collects all JSR166 unit tests as one suite
// */
//public static Test suite()
//{
// TestSuite suite = new TestSuite("JSR166 Unit Tests");

// suite.addTest(new TestSuite(AbstractExecutorServiceTest.class));
// suite.addTest(new TestSuite(AbstractQueueTest.class));
// suite.addTest(new TestSuite(AbstractQueuedSynchronizerTest.class));
// suite.addTest(new TestSuite(ArrayBlockingQueueTest.class));
// suite.addTest(new TestSuite(AtomicBooleanTest.class));
// suite.addTest(new TestSuite(AtomicIntegerArrayTest.class));
// suite.addTest(new TestSuite(AtomicIntegerFieldUpdaterTest.class));
// suite.addTest(new TestSuite(AtomicIntegerTest.class));
// suite.addTest(new TestSuite(AtomicLongArrayTest.class));
// suite.addTest(new TestSuite(AtomicLongFieldUpdaterTest.class));
// suite.addTest(new TestSuite(AtomicLongTest.class));
// suite.addTest(new TestSuite(AtomicMarkableReferenceTest.class));
// suite.addTest(new TestSuite(AtomicReferenceArrayTest.class));
// suite.addTest(new TestSuite(AtomicReferenceFieldUpdaterTest.class));
// suite.addTest(new TestSuite(AtomicReferenceTest.class));
// suite.addTest(new TestSuite(AtomicStampedReferenceTest.class));
// suite.addTest(new TestSuite(ConcurrentHashMapTest.class));
// suite.addTest(new TestSuite(ConcurrentLinkedQueueTest.class));
// suite.addTest(new TestSuite(CopyOnWriteArrayListTest.class));
// suite.addTest(new TestSuite(CopyOnWriteArraySetTest.class));
// suite.addTest(new TestSuite(CountDownLatchTest.class));
// suite.addTest(new TestSuite(CyclicBarrierTest.class));
// suite.addTest(new TestSuite(DelayQueueTest.class));
// suite.addTest(new TestSuite(ExchangerTest.class));
// suite.addTest(new TestSuite(ExecutorsTest.class));
// suite.addTest(new TestSuite(ExecutorCompletionServiceTest.class));
// suite.addTest(new TestSuite(FutureTaskTest.class));
// suite.addTest(new TestSuite(LinkedBlockingQueueTest.class));
// suite.addTest(new TestSuite(LinkedListTest.class));
// suite.addTest(new TestSuite(LockSupportTest.class));
// suite.addTest(new TestSuite(PriorityBlockingQueueTest.class));
// suite.addTest(new TestSuite(PriorityQueueTest.class));
// suite.addTest(new TestSuite(ReentrantLockTest.class));
// suite.addTest(new TestSuite(ReentrantReadWriteLockTest.class));
// suite.addTest(new TestSuite(ScheduledExecutorTest.class));
// suite.addTest(new TestSuite(SemaphoreTest.class));
// suite.addTest(new TestSuite(SynchronousQueueTest.class));
// suite.addTest(new TestSuite(SystemTest.class));
// suite.addTest(new TestSuite(ThreadLocalTest.class));
// suite.addTest(new TestSuite(ThreadPoolExecutorTest.class));
// suite.addTest(new TestSuite(ThreadTest.class));
// suite.addTest(new TestSuite(TimeUnitTest.class));

// return suite;
//}

public static int SHORT_DELAY_MS;
public static int SMALL_DELAY_MS;
public static int MEDIUM_DELAY_MS;
public static int LONG_DELAY_MS;

/**
* Returns the shortest timed delay. This could
* be reimplemented to use for example a Property.
*/
protected int getShortDelay()
{
return 50;
}


/**
* Sets delays as multiples of SHORT_DELAY.
*/
protected void setDelays()
{
SHORT_DELAY_MS = getShortDelay();
SMALL_DELAY_MS = SHORT_DELAY_MS * 5;
MEDIUM_DELAY_MS = SHORT_DELAY_MS * 10;
LONG_DELAY_MS = SHORT_DELAY_MS * 50;
}

/**
* Flag set true if any threadAssert methods fail
*/
internal volatile bool threadFailed;

/**
* Initializes test to indicate that no thread assertions have failed
*/
public override void SetUp()
{
base.SetUp();
setDelays();
threadFailed = false;
}

/**
* Triggers test case failure if any thread assertions have failed
*/
public override void TearDown()
{
assertFalse(threadFailed);
base.TearDown();
}

/**
* Fail, also setting status to indicate current testcase should fail
*/
public void threadFail(string reason)
{
threadFailed = true;
fail(reason);
}

/**
* If expression not true, set status to indicate current testcase
* should fail
*/
public void threadAssertTrue(bool b)
{
if (!b)
{
threadFailed = true;
assertTrue(b);
}
}

/**
* If expression not false, set status to indicate current testcase
* should fail
*/
public void threadAssertFalse(bool b)
{
if (b)
{
threadFailed = true;
assertFalse(b);
}
}

/**
* If argument not null, set status to indicate current testcase
* should fail
*/
public void threadAssertNull(object x)
{
if (x != null)
{
threadFailed = true;
assertNull(x);
}
}

/**
* If arguments not equal, set status to indicate current testcase
* should fail
*/
public void threadAssertEquals(long x, long y)
{
if (x != y)
{
threadFailed = true;
assertEquals(x, y);
}
}

/**
* If arguments not equal, set status to indicate current testcase
* should fail
*/
public void threadAssertEquals(object x, object y)
{
if (x != y && (x == null || !x.equals(y)))
{
threadFailed = true;
assertEquals(x, y);
}
}

/**
* threadFail with message "should throw exception"
*/
public void threadShouldThrow()
{
//try
//{
threadFailed = true;
fail("should throw exception");
//}
//catch (AssertionFailedError e)
//{
// e.printStackTrace();
// throw e;
//}
}

/**
* threadFail with message "Unexpected exception"
*/
public void threadUnexpectedException()
{
threadFailed = true;
fail("Unexpected exception");
}

/**
* threadFail with message "Unexpected exception", with argument
*/
public void threadUnexpectedException(Exception ex)
{
threadFailed = true;
ex.printStackTrace();
fail("Unexpected exception: " + ex);
}

///**
// * Wait out termination of a thread pool or fail doing so
// */
//public void joinPool(ExecutorService exec)
//{
// try
// {
// exec.shutdown();
// assertTrue(exec.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
// }
// catch (SecurityException ok)
// {
// // Allowed in case test doesn't have privs
// }
// catch (InterruptedException ie)
// {
// fail("Unexpected exception");
// }
//}


/**
* fail with message "should throw exception"
*/
public void shouldThrow()
{
fail("Should throw exception");
}

/**
* fail with message "Unexpected exception"
*/
public void unexpectedException()
{
fail("Unexpected exception");
}


// LUCENENET TODO: Complete port
}
}
Loading

0 comments on commit 89b01e6

Please sign in to comment.