| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- using System.Diagnostics;
- using Application.Helpers;
- namespace Application.Tests;
- [TestClass]
- public sealed class SeibroRollingSweepTests
- {
- [TestMethod]
- public async Task RunAsync_UnprocessedFirst_ThenStaleOrder_StableForTies()
- {
- // 미처리(null) 우선(입력 순서 유지), 그다음 오래된(stale) 순
- var targets = new List<(string Key, DateTime? LastUpdatedAt)>
- {
- ("A", new DateTime(2026, 1, 5)),
- ("B", null),
- ("C", new DateTime(2026, 1, 1)),
- ("D", null)
- };
- var processed = new List<string>();
- var count = await SeibroRollingSweep.RunAsync(
- targets: targets,
- fetchAndUpsert: (key, _) => { processed.Add(key); return Task.CompletedTask; },
- maxPerRun: 100,
- delayMs: 0,
- ct: CancellationToken.None);
- Assert.AreEqual(4, count);
- CollectionAssert.AreEqual(new[] { "B", "D", "C", "A" }, processed, "미처리(B,D 입력순) → stale(C=1/1) → 최신(A=1/5)");
- }
- [TestMethod]
- public async Task RunAsync_StopsAfterMaxPerRun()
- {
- var targets = Enumerable.Range(0, 10).Select(c => (Key: c, LastUpdatedAt: (DateTime?)null)).ToList();
- var fetched = 0;
- var count = await SeibroRollingSweep.RunAsync(
- targets: targets,
- fetchAndUpsert: (_, _) => { fetched++; return Task.CompletedTask; },
- maxPerRun: 3,
- delayMs: 0,
- ct: CancellationToken.None);
- Assert.AreEqual(3, count, "maxPerRun 도달 시 즉시 멈춤 (quota 상한)");
- Assert.AreEqual(3, fetched);
- }
- [TestMethod]
- public async Task RunAsync_MaxPerRunZeroOrNegative_FetchesNothing()
- {
- var fetched = 0;
- var count = await SeibroRollingSweep.RunAsync(
- targets: [("A", (DateTime?)null)],
- fetchAndUpsert: (_, _) => { fetched++; return Task.CompletedTask; },
- maxPerRun: 0,
- delayMs: 0,
- ct: CancellationToken.None);
- Assert.AreEqual(0, count);
- Assert.AreEqual(0, fetched, "maxPerRun<=0 이면 fetch 호출 자체가 없다");
- }
- [TestMethod]
- public async Task RunAsync_DelaysBetweenFetches_NotBeforeFirst()
- {
- // 지연 계약: 호출 사이에만 delayMs — 3건 × 60ms → 최소 120ms (첫 호출 전엔 지연 없음)
- var targets = Enumerable.Range(0, 3).Select(c => (Key: c, LastUpdatedAt: (DateTime?)null)).ToList();
- var sw = Stopwatch.StartNew();
- await SeibroRollingSweep.RunAsync(
- targets: targets,
- fetchAndUpsert: (_, _) => Task.CompletedTask,
- maxPerRun: 100,
- delayMs: 60,
- ct: CancellationToken.None);
- Assert.IsTrue(sw.ElapsedMilliseconds >= 120, $"3건이면 사이 지연 2회 ≥ 120ms (실측 {sw.ElapsedMilliseconds}ms)");
- // 단건이면 지연 없음 — delayMs 가 매우 커도 즉시 끝난다
- sw.Restart();
- await SeibroRollingSweep.RunAsync(
- targets: [(0, (DateTime?)null)],
- fetchAndUpsert: (_, _) => Task.CompletedTask,
- maxPerRun: 1,
- delayMs: 30_000,
- ct: CancellationToken.None);
- Assert.IsTrue(sw.ElapsedMilliseconds < 5_000, $"첫 호출 전에는 지연이 없다 (실측 {sw.ElapsedMilliseconds}ms)");
- }
- [TestMethod]
- public async Task RunAsync_EmptyTargets_ReturnsZero()
- {
- var count = await SeibroRollingSweep.RunAsync<string>(
- targets: [],
- fetchAndUpsert: (_, _) => Task.CompletedTask,
- maxPerRun: 100,
- delayMs: 0,
- ct: CancellationToken.None);
- Assert.AreEqual(0, count);
- }
- }
|