blob: a7cfbbe28ccc5f541d10b8d53f9bfd785a3920db [file] [log] [blame]
// Based on tests from Apache Harmony:
// https://github.com/apache/harmony/blob/02970cb7227a335edd2c8457ebdde0195a735733/classlib/modules/concurrent/src/test/java/ThreadPoolExecutorTest.java
using NUnit.Framework;
using System;
using System.Threading;
using System.Threading.Tasks;
#nullable enable
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.
*/
/// <summary>
/// Tests for <see cref="LimitedConcurrencyLevelTaskScheduler"/>.
/// Adapted from Apache Harmony test suite <c>ThreadPoolExecutorTest</c>.
/// </summary>
[TestFixture]
public class TestLimitedConcurrencyLevelTaskScheduler : JSR166TestCase
{
/// <summary>
/// execute successfully executes a runnable
/// </summary>
/// <remarks>
/// LUCENENET Note: Execute is provided in <see cref="JSR166TestCaseExtensions"/>
/// to emulate the behavior of the Java method; it is not in the public
/// API for <see cref="LimitedConcurrencyLevelTaskScheduler"/>. This
/// just helps ensure the class is working as expected.
/// </remarks>
[Test]
public void TestExecute()
{
TaskScheduler p1 = new LimitedConcurrencyLevelTaskScheduler(1);
try
{
p1.Execute(() =>
{
try
{
Thread.Sleep(SHORT_DELAY_MS);
}
catch (ThreadInterruptedException /*e*/)
{
threadUnexpectedException();
}
});
Thread.Sleep(SMALL_DELAY_MS);
}
catch (ThreadInterruptedException /*e*/)
{
unexpectedException();
}
joinPool(p1);
}
/// <summary>
/// getActiveCount increases but doesn't overestimate, when a
/// thread becomes active
/// </summary>
/// <remarks>
/// LUCENENET Note: GetActiveCount is provided in <see cref="JSR166TestCaseExtensions"/>
/// to emulate the behavior of the Java method; it is not in the public
/// API for <see cref="LimitedConcurrencyLevelTaskScheduler"/>. This
/// just helps ensure the class is working as expected.
/// </remarks>
[Test]
public void TestGetActiveCount()
{
TaskScheduler p2 = new LimitedConcurrencyLevelTaskScheduler(2);
assertEquals(0, p2.GetActiveCount());
p2.Execute(MediumRunnable);
try
{
Thread.Sleep(SHORT_DELAY_MS);
}
catch (Exception /*e*/)
{
unexpectedException();
}
// LUCENENET specific - this test is flaky because the thread may not have started yet
// was: assertEquals(1, p2.GetActiveCount());
AssumeTrue($"Expected 1, but got {p2.GetActiveCount()} - this may be a timing issue.", p2.GetActiveCount() == 1);
joinPool(p2);
}
// LUCENENET NOTE: testPrestartCoreThread and testPrestartAllCoreThreads omitted; they are not relevant
/// <summary>
/// getCompletedTaskCount increases, but doesn't overestimate,
/// when tasks complete
/// </summary>
/// <remarks>
/// LUCENENET Note: GetCompletedTaskCount is provided in <see cref="JSR166TestCaseExtensions"/>
/// to emulate the behavior of the Java method; it is not in the public
/// API for <see cref="LimitedConcurrencyLevelTaskScheduler"/>. This
/// just helps ensure the class is working as expected.
/// </remarks>
[Test]
public void TestGetCompletedTaskCount()
{
TaskScheduler p2 = new LimitedConcurrencyLevelTaskScheduler(2);
assertEquals(0, p2.GetCompletedTaskCount());
p2.Execute(ShortRunnable);
try
{
Thread.Sleep(SMALL_DELAY_MS);
}
catch (Exception /*e*/)
{
unexpectedException();
}
// LUCENENET specific - this test is flaky because the thread may not have finished yet
// was: assertEquals(1, p2.GetCompletedTaskCount());
AssumeTrue($"Expected 1, but got {p2.GetCompletedTaskCount()} - this may be a timing issue.", p2.GetCompletedTaskCount() == 1);
// LUCENENET NOTE: not catching SecurityException because that's not relevant here
p2.Shutdown();
joinPool(p2);
}
/// <summary>
/// Tests <see cref="LimitedConcurrencyLevelTaskScheduler.MaximumConcurrencyLevel"/>
/// returns size given in constructor if not otherwise set
/// </summary>
/// <remarks>
/// LUCENENET Note: this is equivalent to the <c>testGetCorePoolSize</c> or
/// <c>testGetMaximumPoolSize</c> methods in the Harmony tests, but we don't
/// have the same concepts or distinction, so just testing to make
/// sure that the maximum concurrency level is set correctly.
/// </remarks>
[Test]
public void TestMaximumConcurrencyLevel()
{
TaskScheduler p1 = new LimitedConcurrencyLevelTaskScheduler(1);
assertEquals(1, p1.MaximumConcurrencyLevel);
joinPool(p1);
}
// LUCENENET NOTE: testGetKeepAliveTime, testGetThreadFactory, testSetThreadFactory,
// testSetThreadFactoryNull, testGetRejectedExecutionHandler, testSetRejectedExecutionHandler,
// testSetRejectedExecutionHandlerNull, testGetLargestPoolSize, and testGetPoolSize omitted; they are not relevant
/// <summary>
/// getTaskCount increases, but doesn't overestimate, when tasks submitted
/// </summary>
/// <remarks>
/// LUCENENET Note: GetTaskCount is provided in <see cref="JSR166TestCaseExtensions"/>
/// to emulate the behavior of the Java method; it is not in the public
/// API for <see cref="LimitedConcurrencyLevelTaskScheduler"/>. This
/// just helps ensure the class is working as expected.
/// </remarks>
[Test]
public void TestGetTaskCount()
{
TaskScheduler p1 = new LimitedConcurrencyLevelTaskScheduler(1);
try
{
assertEquals(0, p1.GetTaskCount());
p1.Execute(MediumRunnable);
Thread.Sleep(SHORT_DELAY_MS);
assertEquals(1, p1.GetTaskCount());
}
catch (Exception /*e*/)
{
unexpectedException();
}
joinPool(p1);
}
/// <summary>
/// <see cref="LimitedConcurrencyLevelTaskScheduler.IsShutdown"/> is false before shutdown, true after
/// </summary>
[Test]
public void TestIsShutdown()
{
var p1 = new LimitedConcurrencyLevelTaskScheduler(1);
assertFalse(p1.IsShutdown);
p1.Shutdown(); // LUCENENET NOTE: not catching SecurityException because that's not relevant here
assertTrue(p1.IsShutdown);
joinPool(p1);
}
/// <summary>
/// isTerminated is false before termination, true after
/// </summary>
/// <remarks>
/// LUCENENET Note: IsTerminated is provided in <see cref="JSR166TestCaseExtensions"/>
/// to emulate the behavior of the Java method; it is not in the public
/// API for <see cref="LimitedConcurrencyLevelTaskScheduler"/>. This
/// just helps ensure the class is working as expected.
/// </remarks>
[Test]
public void TestIsTerminated()
{
TaskScheduler p1 = new LimitedConcurrencyLevelTaskScheduler(1);
assertFalse(p1.IsTerminated());
try
{
p1.Execute(MediumRunnable);
}
finally
{
p1.Shutdown(); // LUCENENET NOTE: not catching SecurityException because that's not relevant here
}
try
{
assertTrue(p1.AwaitTermination(TimeSpan.FromMilliseconds(LONG_DELAY_MS)));
assertTrue(p1.IsTerminated());
}
catch (Exception /*e*/)
{
unexpectedException();
}
}
// LUCENENET NOTE: remainder of methods omitted, could be added as needed.
}
}