mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* Tons of API doc updates * Removed stale test * Removed stale tests * Fixed Skipped Shadow test 1 * Fixed Skipped Shadow test 2 * Fixed Skipped Shadow test 3 * Removed stale test * Removed stale test2 * Explicit unregister of event handler on Application.Driver!.ClearedContents * Added Toplevels to dict * code cleanup * spelling error * Removed stale test3 * Removed stale test4 * Removed stale test5 * added script * tweaked script * tweaked script * Created StressTests project; moved some tests * Created IntegrationTests project; moved some tests * New yml * made old yml just unit tests * Tweaked Button_IsDefault_Raises_Accepted_Correctly * tweaked script * cleaned up ymls * tweakled up ymls * stress tests... * stress tests on ubuntu only * Fixed WindowsDriver in InvokeLeakTest * Fixed WindowsDriver in InvokeLeakTest2 * Added Directory.Packages.props. Added Directory.Build.props * Shortened StressTest time * Removed dupe file. * DemoFiles * Moved all tests to ./Tests dir. * Fixed release build issue * Fixed .sln file * Fixed .sl* files * Fixing ymls * Fixing interation tests * Create link to the file TestHelpers. * Created Tests/UnitTestsParallelizable. Moved all obviously parallelizable tests. Updated yml. * fixing logs * fixing logs2 * fixing logs3 * don't require stress to pass for PRs * Fix a failure? * tweaked script * Coudl this be it? * Moved tons of tests to parallelizable * Fixed some stuff * Script to find duplicate tests * Testing workflows * Updated to v4 * Fix RelativeBasePath issue * Replace powershell to pwsh * Add ignore projects. * Removed dupe unit tests * Code cleanup of tests * Cleaned up test warnings * yml tweak * Moved setter * tweak ymls * just randomly throwing spaghetti at a wall * Enable runing 5 test runners in par * Turned off DEBUG_DISPOSABLE for par tests * RunningUnitTests=true * code cleanup (forcing more Action runs) * DISABLE_DEBUG_IDISPOSABLE * Added View.DebugIDisposable. False by default. * Remobed bogus tareet * Remobed bogus tareet2 * fixed warning * added api doc * fixed warning * fixed warning * fixed warning2 * fixed warning3 * fixed warning4 --------- Co-authored-by: BDisp <bd.bdisp@gmail.com>
236 lines
7.9 KiB
C#
236 lines
7.9 KiB
C#
using Moq;
|
|
|
|
namespace UnitTests.ConsoleDrivers;
|
|
|
|
|
|
public class AnsiRequestSchedulerTests
|
|
{
|
|
private readonly Mock<IAnsiResponseParser> _parserMock;
|
|
private readonly AnsiRequestScheduler _scheduler;
|
|
|
|
private static DateTime _staticNow; // Static value to hold the current time
|
|
|
|
public AnsiRequestSchedulerTests ()
|
|
{
|
|
_parserMock = new Mock<IAnsiResponseParser> (MockBehavior.Strict);
|
|
_staticNow = DateTime.UtcNow; // Initialize static time
|
|
_scheduler = new AnsiRequestScheduler (_parserMock.Object, () => _staticNow);
|
|
}
|
|
|
|
[Fact]
|
|
public void SendOrSchedule_SendsDeviceAttributeRequest_WhenNoOutstandingRequests ()
|
|
{
|
|
// Arrange
|
|
var request = new AnsiEscapeSequenceRequest
|
|
{
|
|
Request = "\u001b[0c", // ESC [ c
|
|
Terminator = "c",
|
|
ResponseReceived = r => { }
|
|
};
|
|
|
|
// we have no outstanding for c already
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (false).Verifiable(Times.Once);
|
|
|
|
// then we should execute our request
|
|
_parserMock.Setup (p => p.ExpectResponse ("c", It.IsAny<Action<string>> (), null, false)).Verifiable (Times.Once);
|
|
|
|
// Act
|
|
bool result = _scheduler.SendOrSchedule (request);
|
|
|
|
|
|
// Assert
|
|
Assert.Empty (_scheduler.QueuedRequests); // We sent it i.e. we did not queue it for later
|
|
Assert.True (result); // Should send immediately
|
|
_parserMock.Verify ();
|
|
}
|
|
[Fact]
|
|
public void SendOrSchedule_QueuesRequest_WhenOutstandingRequestExists ()
|
|
{
|
|
// Arrange
|
|
var request1 = new AnsiEscapeSequenceRequest
|
|
{
|
|
Request = "\u001b[0c", // ESC [ 0 c
|
|
Terminator = "c",
|
|
ResponseReceived = r => { }
|
|
};
|
|
|
|
// Parser already has an ongoing request for "c"
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (true).Verifiable (Times.Once);
|
|
|
|
// Act
|
|
var result = _scheduler.SendOrSchedule (request1);
|
|
|
|
// Assert
|
|
Assert.Single (_scheduler.QueuedRequests); // Ensure only one request is in the queue
|
|
Assert.False (result); // Should be queued
|
|
_parserMock.Verify ();
|
|
}
|
|
|
|
|
|
[Fact]
|
|
public void RunSchedule_ThrottleNotExceeded_AllowSend ()
|
|
{
|
|
// Arrange
|
|
var request = new AnsiEscapeSequenceRequest
|
|
{
|
|
Request = "\u001b[0c", // ESC [ 0 c
|
|
Terminator = "c",
|
|
ResponseReceived = r => { }
|
|
};
|
|
|
|
// Set up to expect no outstanding request for "c" i.e. parser instantly gets response and resolves it
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (false).Verifiable(Times.Exactly (2));
|
|
_parserMock.Setup (p => p.ExpectResponse ("c", It.IsAny<Action<string>> (), null, false)).Verifiable (Times.Exactly (2));
|
|
|
|
_scheduler.SendOrSchedule (request);
|
|
|
|
// Simulate time passing beyond throttle
|
|
SetTime (101); // Exceed throttle limit
|
|
|
|
|
|
// Act
|
|
|
|
// Send another request after the throttled time limit
|
|
var result = _scheduler.SendOrSchedule (request);
|
|
|
|
// Assert
|
|
Assert.Empty (_scheduler.QueuedRequests); // Should send and clear the request
|
|
Assert.True (result); // Should have found and sent the request
|
|
_parserMock.Verify ();
|
|
}
|
|
|
|
[Fact]
|
|
public void RunSchedule_ThrottleExceeded_QueueRequest ()
|
|
{
|
|
// Arrange
|
|
var request = new AnsiEscapeSequenceRequest
|
|
{
|
|
Request = "\u001b[0c", // ESC [ 0 c
|
|
Terminator = "c",
|
|
ResponseReceived = r => { }
|
|
};
|
|
|
|
// Set up to expect no outstanding request for "c" i.e. parser instantly gets response and resolves it
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (false).Verifiable (Times.Exactly (2));
|
|
_parserMock.Setup (p => p.ExpectResponse ("c", It.IsAny<Action<string>> (), null, false)).Verifiable (Times.Exactly (2));
|
|
|
|
_scheduler.SendOrSchedule (request);
|
|
|
|
// Simulate time passing
|
|
SetTime (55); // Does not exceed throttle limit
|
|
|
|
|
|
// Act
|
|
|
|
// Send another request after the throttled time limit
|
|
var result = _scheduler.SendOrSchedule (request);
|
|
|
|
// Assert
|
|
Assert.Single (_scheduler.QueuedRequests); // Should have been queued
|
|
Assert.False(result); // Should have been queued
|
|
|
|
// Throttle still not exceeded
|
|
Assert.False(_scheduler.RunSchedule ());
|
|
|
|
SetTime (90);
|
|
|
|
// Throttle still not exceeded
|
|
Assert.False (_scheduler.RunSchedule ());
|
|
|
|
SetTime (105);
|
|
|
|
// Throttle exceeded - so send the request
|
|
Assert.True (_scheduler.RunSchedule ());
|
|
|
|
_parserMock.Verify ();
|
|
}
|
|
|
|
[Fact]
|
|
public void EvictStaleRequests_RemovesStaleRequest_AfterTimeout ()
|
|
{
|
|
// Arrange
|
|
var request1 = new AnsiEscapeSequenceRequest
|
|
{
|
|
Request = "\u001b[0c",
|
|
Terminator = "c",
|
|
ResponseReceived = r => { }
|
|
};
|
|
|
|
// Send
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (false).Verifiable (Times.Once);
|
|
_parserMock.Setup (p => p.ExpectResponse ("c", It.IsAny<Action<string>> (), null, false)).Verifiable (Times.Exactly (2));
|
|
|
|
Assert.True (_scheduler.SendOrSchedule (request1));
|
|
|
|
// Parser already has an ongoing request for "c"
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (true).Verifiable (Times.Exactly (2));
|
|
|
|
// Cannot send because there is already outstanding request
|
|
Assert.False(_scheduler.SendOrSchedule (request1));
|
|
Assert.Single (_scheduler.QueuedRequests);
|
|
|
|
// Simulate request going stale
|
|
SetTime (5001); // Exceeds stale timeout
|
|
|
|
// Parser should be told to give up on this one (evicted)
|
|
_parserMock.Setup (p => p.StopExpecting ("c", false))
|
|
.Callback (() =>
|
|
{
|
|
// When we tell parser to evict - it should now tell us it is no longer expecting
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (false).Verifiable (Times.Once);
|
|
}).Verifiable ();
|
|
|
|
// When we send again the evicted one should be
|
|
var evicted = _scheduler.RunSchedule ();
|
|
|
|
Assert.True (evicted); // Stale request should be evicted
|
|
Assert.Empty (_scheduler.QueuedRequests);
|
|
|
|
// Assert
|
|
_parserMock.Verify ();
|
|
}
|
|
|
|
[Fact]
|
|
public void RunSchedule_DoesNothing_WhenQueueIsEmpty ()
|
|
{
|
|
// Act
|
|
var result = _scheduler.RunSchedule ();
|
|
|
|
// Assert
|
|
Assert.False (result); // No requests to process
|
|
Assert.Empty (_scheduler.QueuedRequests);
|
|
}
|
|
|
|
[Fact]
|
|
public void SendOrSchedule_ManagesIndependentTerminatorsCorrectly ()
|
|
{
|
|
// Arrange
|
|
var request1 = new AnsiEscapeSequenceRequest { Request = "\u001b[0c", Terminator = "c", ResponseReceived = r => { } };
|
|
var request2 = new AnsiEscapeSequenceRequest { Request = "\u001b[0x", Terminator = "x", ResponseReceived = r => { } };
|
|
|
|
// Already have a 'c' ongoing
|
|
_parserMock.Setup (p => p.IsExpecting ("c")).Returns (true).Verifiable (Times.Once);
|
|
|
|
// 'x' is free
|
|
_parserMock.Setup (p => p.IsExpecting ("x")).Returns (false).Verifiable (Times.Once);
|
|
_parserMock.Setup (p => p.ExpectResponse ("x", It.IsAny<Action<string>> (), null, false)).Verifiable (Times.Once);
|
|
|
|
// Act
|
|
var a = _scheduler.SendOrSchedule (request1);
|
|
var b = _scheduler.SendOrSchedule (request2);
|
|
|
|
// Assert
|
|
Assert.False (a);
|
|
Assert.True (b);
|
|
Assert.Equal(request1, Assert.Single (_scheduler.QueuedRequests));
|
|
_parserMock.Verify ();
|
|
}
|
|
|
|
|
|
private void SetTime (int milliseconds)
|
|
{
|
|
// This simulates the passing of time by setting the Now function to return a specific time.
|
|
var newNow = _staticNow.AddMilliseconds (milliseconds);
|
|
_scheduler.Now = () => newNow;
|
|
}
|
|
} |