2023-06-23 09:38:30 +00:00
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
|
|
|
namespace ContinuousTests
|
|
|
|
|
{
|
|
|
|
|
public class TestHandle
|
|
|
|
|
{
|
|
|
|
|
private readonly List<MethodMoment> moments = new List<MethodMoment>();
|
|
|
|
|
|
|
|
|
|
public TestHandle(ContinuousTest test)
|
|
|
|
|
{
|
|
|
|
|
Test = test;
|
|
|
|
|
|
|
|
|
|
ReflectTestMoments();
|
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
var testName = test.GetType().Name;
|
|
|
|
|
if (!moments.Any()) throw new Exception($"Test '{testName}' has no moments.");
|
|
|
|
|
if (moments.Count != moments.Select(m => m.Moment).Distinct().Count()) throw new Exception($"Test '{testName}' has duplicate moments");
|
2023-06-23 09:38:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ContinuousTest Test { get; }
|
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
public int GetEarliestMoment()
|
2023-06-23 09:38:30 +00:00
|
|
|
|
{
|
2023-06-25 07:53:10 +00:00
|
|
|
|
return moments.Min(m => m.Moment);
|
2023-06-23 09:38:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetLastMoment()
|
|
|
|
|
{
|
|
|
|
|
return moments.Max(m => m.Moment);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
public int? GetNextMoment(int currentMoment)
|
|
|
|
|
{
|
2023-06-25 08:50:01 +00:00
|
|
|
|
var remainingMoments = moments.Where(m => m.Moment > currentMoment).ToArray();
|
2023-06-25 07:53:10 +00:00
|
|
|
|
if (!remainingMoments.Any()) return null;
|
|
|
|
|
return remainingMoments.Min(m => m.Moment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void InvokeMoment(int currentMoment, Action<string> beforeInvoke)
|
2023-06-23 09:38:30 +00:00
|
|
|
|
{
|
|
|
|
|
var moment = moments.SingleOrDefault(m => m.Moment == currentMoment);
|
|
|
|
|
if (moment == null) return;
|
|
|
|
|
|
2023-06-25 07:53:10 +00:00
|
|
|
|
lock (MomentLock.Lock)
|
|
|
|
|
{
|
|
|
|
|
beforeInvoke(moment.Method.Name);
|
|
|
|
|
moment.Method.Invoke(Test, Array.Empty<object>());
|
|
|
|
|
}
|
2023-06-23 09:38:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ReflectTestMoments()
|
|
|
|
|
{
|
|
|
|
|
var methods = Test.GetType().GetMethods()
|
|
|
|
|
.Where(m => m.GetCustomAttributes(typeof(TestMomentAttribute), false).Length > 0)
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
|
|
foreach (var method in methods)
|
|
|
|
|
{
|
|
|
|
|
var moment = method.GetCustomAttribute<TestMomentAttribute>();
|
|
|
|
|
if (moment != null && moment.T >= 0)
|
|
|
|
|
{
|
|
|
|
|
moments.Add(new MethodMoment(method, moment.T));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class MethodMoment
|
|
|
|
|
{
|
|
|
|
|
public MethodMoment(MethodInfo method, int moment)
|
|
|
|
|
{
|
|
|
|
|
Method = method;
|
|
|
|
|
Moment = moment;
|
2023-06-25 08:50:01 +00:00
|
|
|
|
|
|
|
|
|
if (moment < 0) throw new Exception("Moment must be zero or greater.");
|
2023-06-23 09:38:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MethodInfo Method { get; }
|
|
|
|
|
public int Moment { get; }
|
|
|
|
|
}
|
2023-06-25 07:53:10 +00:00
|
|
|
|
|
|
|
|
|
public static class MomentLock
|
|
|
|
|
{
|
|
|
|
|
public static readonly object Lock = new();
|
|
|
|
|
}
|
2023-06-23 09:38:30 +00:00
|
|
|
|
}
|