| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- using System.Diagnostics;
- namespace UnitTests.ApplicationTests;
- /// <summary>
- /// Tests for TimedEvents class, focusing on high-resolution timing with Stopwatch.
- /// </summary>
- public class TimedEventsTests
- {
- [Fact]
- public void HighFrequency_Concurrent_Invocations_No_Lost_Timeouts ()
- {
- var timedEvents = new Terminal.Gui.App.TimedEvents ();
- var counter = 0;
- var expected = 1000;
- var completed = new ManualResetEventSlim (false);
- // Add many timeouts with TimeSpan.Zero concurrently
- Parallel.For (0, expected, i =>
- {
- timedEvents.Add (TimeSpan.Zero, () =>
- {
- var current = Interlocked.Increment (ref counter);
- if (current == expected)
- {
- completed.Set ();
- }
- return false; // One-shot
- });
- });
- // Run timers multiple times to ensure all are processed
- for (int i = 0; i < 10; i++)
- {
- timedEvents.RunTimers ();
- if (completed.IsSet)
- {
- break;
- }
- Thread.Sleep (10);
- }
- Assert.Equal (expected, counter);
- }
- [Fact]
- public void GetTimestampTicks_Provides_High_Resolution ()
- {
- var timedEvents = new Terminal.Gui.App.TimedEvents ();
-
- // Add multiple timeouts with TimeSpan.Zero rapidly
- var timestamps = new List<long> ();
-
- // Single event handler to capture all timestamps
- EventHandler<Terminal.Gui.App.TimeoutEventArgs>? handler = null;
- handler = (s, e) =>
- {
- timestamps.Add (e.Ticks);
- };
-
- timedEvents.Added += handler;
-
- for (int i = 0; i < 100; i++)
- {
- timedEvents.Add (TimeSpan.Zero, () => false);
- }
-
- timedEvents.Added -= handler;
- // Verify that we got timestamps
- Assert.True (timestamps.Count > 0, $"Should have captured timestamps. Got {timestamps.Count}");
-
- // Verify that we got unique timestamps (or very close)
- // With Stopwatch, we should have much better resolution than DateTime.UtcNow
- var uniqueTimestamps = timestamps.Distinct ().Count ();
-
- // We should have mostly unique timestamps
- // Allow some duplicates due to extreme speed, but should be > 50% unique
- Assert.True (uniqueTimestamps > timestamps.Count / 2,
- $"Expected more unique timestamps. Got {uniqueTimestamps} unique out of {timestamps.Count} total");
- }
- [Fact]
- public void TimeSpan_Zero_Executes_Immediately ()
- {
- var timedEvents = new Terminal.Gui.App.TimedEvents ();
- var executed = false;
- timedEvents.Add (TimeSpan.Zero, () =>
- {
- executed = true;
- return false;
- });
- Assert.True (timedEvents.Timeouts.Keys [0] > 0);
- // Should execute on first RunTimers call
- timedEvents.RunTimers ();
- Assert.Empty (timedEvents.Timeouts);
- Assert.True (executed);
- }
- [Fact]
- public void Multiple_TimeSpan_Zero_Timeouts_All_Execute ()
- {
- var timedEvents = new Terminal.Gui.App.TimedEvents ();
- var executeCount = 0;
- var expected = 100;
- for (int i = 0; i < expected; i++)
- {
- timedEvents.Add (TimeSpan.Zero, () =>
- {
- Interlocked.Increment (ref executeCount);
- return false;
- });
- }
- // Run timers once
- timedEvents.RunTimers ();
- Assert.Equal (expected, executeCount);
- }
- }
|