| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- #nullable enable
- 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 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,
- () =>
- {
- int current = Interlocked.Increment (ref counter);
- if (current == expected)
- {
- completed.Set ();
- }
- return false; // One-shot
- });
- });
- // Run timers multiple times to ensure all are processed
- for (var 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 TimedEvents ();
- // Add multiple timeouts with TimeSpan.Zero rapidly
- List<long> timestamps = new ();
- // Single event handler to capture all timestamps
- EventHandler<TimeoutEventArgs>? handler = null;
- handler = (s, e) => { timestamps.Add (e.Ticks); };
- timedEvents.Added += handler;
- for (var 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
- int 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 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 TimedEvents ();
- var executeCount = 0;
- var expected = 100;
- for (var i = 0; i < expected; i++)
- {
- timedEvents.Add (
- TimeSpan.Zero,
- () =>
- {
- Interlocked.Increment (ref executeCount);
- return false;
- });
- }
- // Run timers once
- timedEvents.RunTimers ();
- Assert.Equal (expected, executeCount);
- }
- }
|