paulirwin commented on code in PR #1125:
URL: https://github.com/apache/lucenenet/pull/1125#discussion_r1930531266


##########
src/dotnet/Lucene.Net.TestFramework.TestData.NUnit/TestUtilities/TestBuilder.cs:
##########
@@ -0,0 +1,260 @@
+// Source: 
https://github.com/nunit/nunit/blob/v3.14.0/src/NUnitFramework/TestBuilder.cs
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading;
+using NUnit.Framework;
+using NUnit.Compatibility;
+using NUnit.Framework.Interfaces;
+using NUnit.Framework.Internal.Builders;
+using NUnit.Framework.Internal;
+using NUnit.Framework.Internal.Commands;
+using NUnit.Framework.Internal.Execution;
+using System.Linq;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+
+namespace Lucene.Net.NUnit.TestUtilities
+{
+    #region Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT 
License.
+
+    // Copyright (c) 2021 Charlie Poole, Rob Prouse
+    // 
+    // Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    // of this software and associated documentation files (the "Software"), 
to deal
+    // in the Software without restriction, including without limitation the 
rights
+    // to use, copy, modify, merge, publish, distribute, sublicense, and/or 
sell
+    // copies of the Software, and to permit persons to whom the Software is
+    // furnished to do so, subject to the following conditions:
+    // 
+    // The above copyright notice and this permission notice shall be included 
in
+    // all copies or substantial portions of the Software.
+    // 
+    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
OR
+    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE
+    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
IN
+    // THE SOFTWARE.
+
+    #endregion
+
+    /// <summary>
+    /// Utility Class used to build and run NUnit tests used as test data
+    /// </summary>
+    public static class TestBuilder
+    {
+        #region Build Tests
+
+        public static TestSuite MakeSuite(string name)
+        {
+            return new TestSuite(name);
+        }
+
+        public static TestSuite MakeFixture(Type type)
+        {
+            //return (TestSuite)new DefaultSuiteBuilder().BuildFrom(new 
TypeWrapper(type));
+            TestSuite suite = (TestSuite)new 
DefaultSuiteBuilder().BuildFrom(new TypeWrapper(type));
+
+            // LUCENENET: We wrapped our TestSuite in another TestSuite
+            // (SetUpFixture), so we need to get the child test (the class).
+            if (suite is not null && 
suite.TypeInfo.Type.Equals(typeof(LuceneTestCase.SetUpFixture)))
+            {
+                suite = (TestSuite)suite.Tests[0];
+            }
+            return suite;
+        }
+
+        public static TestSuite MakeFixture(object fixture)
+        {
+            TestSuite suite = MakeFixture(fixture.GetType());
+            suite.Fixture = fixture;
+            return suite;
+        }
+
+        public static TestSuite MakeParameterizedMethodSuite(Type type, string 
methodName)
+        {
+            var suite = MakeTestFromMethod(type, methodName) as TestSuite;
+            Assert.NotNull(suite, "Unable to create parameterized suite - most 
likely there is no data provided");
+            return suite;
+        }
+
+        public static TestMethod MakeTestCase(Type type, string methodName)
+        {
+            var test = MakeTestFromMethod(type, methodName) as TestMethod;
+            Assert.NotNull(test, "Unable to create TestMethod from {0}", 
methodName);
+
+            return test;
+        }
+
+        // Will return either a ParameterizedMethodSuite or an NUnitTestMethod
+        // depending on whether the method takes arguments or not
+        internal static Test MakeTestFromMethod(Type type, string methodName)
+        {
+            var method = type.GetMethod(methodName, BindingFlags.Static | 
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+
+            if (method == null)
+                Assert.Fail("Method not found: " + methodName);
+            var test = new DefaultTestCaseBuilder().BuildFrom(new 
MethodWrapper(type, method));
+            // LUCENENET: We need to initialize the RandomizedContext for our 
custom attributes to work.
+            InitializeTestFixture(test);
+            return test;
+        }
+
+        internal static void InitializeTestFixture(Test fixture)
+        {
+            var random = new J2N.Randomizer(); // LUCENENET TOOD: Initilize 
this to make it repeatable?
+            long initialSeed = random.NextInt64();
+            long testSeed = random.NextInt64();
+            var randomizedContext = new RandomizedContext(fixture, 
fixture.TypeInfo.Assembly, initialSeed, testSeed);
+            _ = new 
LuceneRandomSeedInitializer().InitializeTestFixture(fixture, randomizedContext);
+        }
+
+        #endregion
+
+        #region Create WorkItems
+
+        public static WorkItem CreateWorkItem(Type type)
+        {
+            return CreateWorkItem(MakeFixture(type));
+        }
+
+        public static WorkItem CreateWorkItem(Type type, string methodName)
+        {
+            return CreateWorkItem(MakeTestFromMethod(type, methodName));
+        }
+
+        public static WorkItem CreateWorkItem(Test test)
+        {
+            var context = new TestExecutionContext();
+            context.Dispatcher = new SuperSimpleDispatcher();
+
+            return CreateWorkItem(test, context);
+        }
+
+        public static WorkItem CreateWorkItem(Test test, object testObject)
+        {
+            var context = new TestExecutionContext();
+            context.TestObject = testObject;
+            context.Dispatcher = new SuperSimpleDispatcher();
+
+            return CreateWorkItem(test, context);
+        }
+
+        public static WorkItem CreateWorkItem(Test test, TestExecutionContext 
context)
+        {
+            // LUCENENET: IDebugger is internal, so our only options are to 
use this obsolete method or to use Reflection.
+#pragma warning disable CS0618 // Type or member is obsolete
+            var work = WorkItemBuilder.CreateWorkItem(test, TestFilter.Empty, 
true);
+#pragma warning restore CS0618 // Type or member is obsolete
+            work.InitializeContext(context);
+
+            return work;
+        }
+
+        #endregion
+
+        #region Run Tests
+
+        public static ITestResult RunTestFixture(Type type)
+        {
+            return RunTest(MakeFixture(type), null);
+        }
+
+        public static ITestResult RunTestFixture(object fixture)
+        {
+            return RunTest(MakeFixture(fixture), fixture);
+        }
+
+        public static ITestResult RunParameterizedMethodSuite(Type type, 
string methodName)
+        {
+            var suite = MakeParameterizedMethodSuite(type, methodName);
+
+            object testObject = null;
+            if (!type.IsStatic())
+                testObject = Reflect.Construct(type);
+
+            return RunTest(suite, testObject);
+        }
+
+        public static ITestResult RunTestCase(Type type, string methodName)
+        {
+            var testMethod = MakeTestCase(type, methodName);
+
+            object testObject = null;
+            if (!type.IsStatic())
+                testObject = Reflect.Construct(type);
+
+            return RunTest(testMethod, testObject);
+        }
+
+        public static ITestResult RunTestCase(object fixture, string 
methodName)
+        {
+            var testMethod = MakeTestCase(fixture.GetType(), methodName);
+
+            return RunTest(testMethod, fixture);
+        }
+
+        public static ITestResult RunAsTestCase(Action action)
+        {
+            var method = action.GetMethodInfo();
+            var testMethod = MakeTestCase(method.DeclaringType, method.Name);
+            return RunTest(testMethod);
+        }
+
+        public static ITestResult RunTest(Test test)
+        {
+            return RunTest(test, null);
+        }
+
+        public static ITestResult RunTest(Test test, object testObject)
+        {
+            return ExecuteWorkItem(CreateWorkItem(test, testObject));
+        }
+
+        public static ITestResult ExecuteWorkItem(WorkItem work)
+        {
+            work.Execute();
+
+            // TODO: Replace with an event - but not while method is static
+            while (work.State != WorkItemState.Complete)
+            {
+                Thread.Sleep(1);

Review Comment:
   I was debating whether or not to comment this, because it could end up being 
pretty wasteful especially on multi-core laptops on battery power when 
developing this, but I'll post it for posterity anyways. I was thinking about 
whether SpinWait might be better here than sleeping for 1ms to avoid the thread 
blocking overhead. But perhaps not; many/most of our tests take longer than 
single-digit milliseconds, so that might be too wasteful in terms of CPU if it 
almost always exhausts its spinning state before yielding. (SpinWait has some 
optimizations that will prevent it from spinning too long or unnecessarily, and 
will always yield on single-core computers, i.e. containers/build agents that 
are single core.) If not SpinWait, it might also be worth considering an 
exponential backoff up to some maximum delay, maybe 256ms (2^8), so that it's 
not in a 1ms-tight loop. Or, another option, maybe we could 
Monitor.Wait/PulseAll on the WorkItem or some state within it. Either way, I 
just wonde
 r if there's some better option than this tight sleep loop here.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@lucenenet.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to