Skip to content

Commit

Permalink
tests!!!
Browse files Browse the repository at this point in the history
  • Loading branch information
LolaLollipop committed Nov 29, 2023
1 parent 030ceca commit 809e4ca
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 17 deletions.
5 changes: 3 additions & 2 deletions RueI/Main.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace RueI;

using System.Reflection;
using static UnityAlternative;

/*********\
* /\_/\ *
Expand Down Expand Up @@ -31,7 +32,7 @@ static Main()

if (!StartupArgs.Args.Contains("-noRMsg", StringComparison.OrdinalIgnoreCase)) // TODO: make this work
{
ServerConsole.AddLog($"[Info] [RueI] Thank you for using RueI! Running v{Version.ToString(3)}", ConsoleColor.Yellow);
Provider.Log($"[Info] [RueI] Thank you for using RueI! Running v{Version.ToString(3)}");
}

try
Expand All @@ -40,7 +41,7 @@ static Main()
}
catch(Exception)
{
ServerConsole.AddLog("[Warn] [RueI] Could not load Harmony patches.", ConsoleColor.Yellow);
Provider.Log("[Warn] [RueI] Could not load Harmony patches.");
}

_ = CharacterLengths.Lengths.Count; // force static initializer
Expand Down
8 changes: 4 additions & 4 deletions RueI/RueI/Events/EventArgs/RateLimitFinishedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
using RueI.Displays;

/// <summary>
/// Contains all information after a player's <see cref="DisplayCoordinator"/> is updated.
/// Contains all information after a player's <see cref="DisplayCore"/> is updated.
/// </summary>
public class DisplayUpdatedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="DisplayUpdatedEventArgs"/> class.
/// </summary>
/// <param name="referenceHub">The hub of the player.</param>
/// <param name="displayCord">The DisplayCore .</param>
/// <param name="displayCord">The <see cref="DisplayCore"/> to use..</param>
public DisplayUpdatedEventArgs(ReferenceHub referenceHub, DisplayCore displayCord)
{
ReferenceHub = referenceHub;
DisplayCoordinator = displayCord;
DisplayCore = displayCord;
}

/// <summary>
Expand All @@ -26,5 +26,5 @@ public DisplayUpdatedEventArgs(ReferenceHub referenceHub, DisplayCore displayCor
/// <summary>
/// Gets the DisplayCore of the player.
/// </summary>
public DisplayCore DisplayCoordinator { get; }
public DisplayCore DisplayCore { get; }
}
150 changes: 150 additions & 0 deletions RueI/UnityAlternative.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
namespace RueI;

using eMEC;
using MEC;
using RueI.Extensions;
using UnityEngine;
using static RueI.NonUnityProvider;

/// <summary>
/// Defines the base class for a provider of methods that may or may not use Unity.
/// </summary>
public abstract class UnityAlternative
{
/// <summary>
/// Represents a generalized handler for an async operation.
/// </summary>
public interface IAsyncOperation : IDisposable
{
/// <summary>
/// Gets a value indicating whether or not this operation is handling.
/// </summary>
public bool IsRunning { get; }

/// <summary>
/// Cancels this operation.
/// </summary>
public void Cancel();
}

/// <summary>
/// Gets the current <see cref="UnityAlternative"/> of the application.
/// </summary>
public static UnityAlternative Provider { get; } = GetProvider();

/// <summary>
/// Logs a message to the console.
/// </summary>
/// <param name="message">The message to log.</param>
public abstract void Log(string message);

/// <summary>
/// Performs an async operation.
/// </summary>
/// <param name="span">How long until the action should be ran.</param>
/// <param name="action">The action to run when finished.</param>
public abstract IAsyncOperation PerformAsync(TimeSpan span, Action action);

private static UnityAlternative GetProvider()
{
try
{
_ = Object.FindObjectOfType<ReferenceHub>();
return new UnityProvider();
}
catch(Exception)
{
return new NonUnityProvider();
}
}
}

/// <summary>
/// Provides non-Unity alternatives for the <see cref="UnityProvider"/> of the application.
/// </summary>
public class NonUnityProvider : UnityAlternative
{
/// <inheritdoc/>
public override void Log(string message) => Console.WriteLine(message);

/// <inheritdoc/>
public override IAsyncOperation PerformAsync(TimeSpan span, Action action) => new TaskAsyncOperation(span, action);

/// <summary>
/// Represents an async operation using a <see cref="Task"/>.
/// </summary>
public class TaskAsyncOperation : IAsyncOperation
{
private readonly Task task;
private readonly CancellationTokenSource source;

/// <summary>
/// Initializes a new instance of the <see cref="TaskAsyncOperation"/> class, and then immediately runs.
/// </summary>
/// <param name="span">How long until the action should be ran.</param>
/// <param name="action">The action to run when finished.</param>
public TaskAsyncOperation(TimeSpan span, Action action)
{
source = new();
task = Task.Run(async () =>
{
await Task.Delay(span);
action();
});
}

/// <inheritdoc/>
public bool IsRunning => !task.IsCompleted;

/// <inheritdoc/>
public void Cancel() => source.Cancel();

/// <summary>
/// Disposes this async operation.
/// </summary>
public void Dispose() => source.Dispose();
}
}

/// <summary>
/// Provides Unity methods for the application.
/// </summary>
public class UnityProvider : UnityAlternative
{
/// <inheritdoc/>
public override void Log(string message) => ServerConsole.AddLog(message, ConsoleColor.Yellow);

/// <inheritdoc/>
public override IAsyncOperation PerformAsync(TimeSpan span, Action action) => new MECAsyncOperation(span, action);

/// <summary>
/// Represents an async operation using a <see cref="Task"/>.
/// </summary>
public class MECAsyncOperation : IAsyncOperation
{
private readonly CoroutineHandle handle;

/// <summary>
/// Initializes a new instance of the <see cref="MECAsyncOperation"/> class, and then immediately runs.
/// </summary>
/// <param name="span">How long until the action should be ran.</param>
/// <param name="action">The action to run when finished.</param>
public MECAsyncOperation(TimeSpan span, Action action)
{
handle = Timing.CallDelayed(((float)span.TotalSeconds).Max(0), action);
}

/// <inheritdoc/>
public bool IsRunning => handle.IsRunning;

/// <inheritdoc/>
public void Cancel() => Timing.KillCoroutines(handle);

/// <summary>
/// Disposes this MEC operation.
/// </summary>
public void Dispose()
{
}
}
}
32 changes: 21 additions & 11 deletions RueI/eMEC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ namespace eMEC;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using MEC;
using RueI.Extensions;
using RueI;
using static RueI.UnityAlternative;

/// <summary>
/// Provides extensions for working with MEC. The primary purpose is to provide better nullable functionality.
Expand Down Expand Up @@ -57,6 +58,8 @@ public interface ITaskable
public class UpdateTask : TaskBase
{
private readonly Stopwatch stopwatch = new();
private TimeSpan? storedTimeLeft;
private bool isPaused = false;

/// <summary>
/// Gets or sets a method that will be run when the task is finished.
Expand Down Expand Up @@ -88,7 +91,7 @@ public class UpdateTask : TaskBase
[MemberNotNullWhen(returnValue: true, nameof(ElapsedTime))]
[MemberNotNullWhen(returnValue: true, nameof(Action))]
[MemberNotNullWhen(returnValue: true, nameof(Length))]
public override bool IsRunning => ch?.IsRunningOrPaused() ?? false;
public override bool IsRunning => isPaused || (operation?.IsRunning ?? false);

/// <summary>
/// Starts the task.
Expand All @@ -101,7 +104,7 @@ public void Start(TimeSpan length, Action action)
Action = action;
Length = length;
stopwatch.Start();
ch = Timing.CallDelayed(((float)length.TotalSeconds).Max(0), () =>
operation = Provider.PerformAsync(length, () =>
{
Action();
ResetState();
Expand Down Expand Up @@ -154,7 +157,7 @@ public void ChangeLength(TimeSpan newLength)

if (newTime > TimeSpan.Zero)
{
ch?.Kill();
operation.Cancel();
Start(newTime, Action);
}
else
Expand All @@ -172,7 +175,9 @@ public void Pause()
{
if (IsRunning)
{
Timing.PauseCoroutines(ch.Value);
storedTimeLeft = TimeLeft;
isPaused = true;
operation?.Cancel();
stopwatch.Stop();
}
}
Expand All @@ -182,9 +187,14 @@ public void Pause()
/// </summary>
public void Resume()
{
if (IsRunning)
if (IsRunning && isPaused)
{
Timing.ResumeCoroutines(ch.Value);
operation = Provider.PerformAsync(Length.Value, () =>
{
Action();
ResetState();
});

stopwatch.Start();
}
}
Expand All @@ -204,7 +214,7 @@ protected override void ResetState()
/// </summary>
public abstract class TaskBase : ITaskable
{
protected CoroutineHandle? ch;
protected IAsyncOperation? operation;

Check warning on line 217 in RueI/eMEC.cs

View workflow job for this annotation

GitHub Actions / build_and_test (Release)

Missing XML comment for publicly visible type or member 'TaskBase.operation'

Check warning on line 217 in RueI/eMEC.cs

View workflow job for this annotation

GitHub Actions / build_and_test (Release)

Missing XML comment for publicly visible type or member 'TaskBase.operation'

/// <summary>
/// Initializes a new instance of the <see cref="TaskBase"/> class.
Expand Down Expand Up @@ -233,7 +243,7 @@ public TaskBase()
/// <summary>
/// Gets a value indicating whether or not this task is currently running.
/// </summary>
[MemberNotNullWhen(returnValue: true, nameof(ch))]
[MemberNotNullWhen(returnValue: true, nameof(operation))]
public abstract bool IsRunning { get; }

/// <inheritdoc/>
Expand All @@ -244,7 +254,7 @@ public TaskBase()
/// </summary>
public virtual void End()
{
ch?.Kill();
operation?.Cancel();
ResetState();
}

Expand All @@ -256,7 +266,7 @@ public virtual void End()

protected virtual void ResetState()

Check warning on line 267 in RueI/eMEC.cs

View workflow job for this annotation

GitHub Actions / build_and_test (Release)

Missing XML comment for publicly visible type or member 'TaskBase.ResetState()'

Check warning on line 267 in RueI/eMEC.cs

View workflow job for this annotation

GitHub Actions / build_and_test (Release)

Missing XML comment for publicly visible type or member 'TaskBase.ResetState()'
{
ch = null;
operation = null;
}
}

Expand Down
27 changes: 27 additions & 0 deletions RueITests/TestMain.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using eMEC;
using RueI;

namespace RueITest;

[TestClass]
public class TestGeneral
{
[TestMethod]
public void TestMain()
{
RueI.Main.EnsureInit();
}

[TestMethod]
public async Task TestEMEC()
{
bool wasSuccessful = false;

UpdateTask task = new();
task.Start(TimeSpan.FromMilliseconds(100), () => wasSuccessful = true);

await Task.Delay(500);

Assert.IsTrue(wasSuccessful);
}
}

0 comments on commit 809e4ca

Please sign in to comment.