public void StatusResultsOrganizerTime() { using (AmbientClock.Pause()) { StatusResultsOrganizer organizer; string o; organizer = new StatusResultsOrganizer(); StatusResults source1Root = new StatusResults(null, null, AmbientClock.UtcNow, 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHeterogenous, new StatusResults[] { new StatusResults(null, "/Target1", AmbientClock.UtcNow.AddSeconds(2), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part1", AmbientClock.UtcNow.AddSeconds(2), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), new StatusResults(null, "/Target2", AmbientClock.UtcNow.AddSeconds(3), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part2", AmbientClock.UtcNow.AddSeconds(3), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), new StatusResults(null, "/Target3", AmbientClock.UtcNow.AddSeconds(1), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part3", AmbientClock.UtcNow.AddSeconds(1), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), }); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); StatusResults source2Root = new StatusResults(null, null, AmbientClock.UtcNow.AddSeconds(5), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHeterogenous, new StatusResults[] { new StatusResults(null, "/Target1", AmbientClock.UtcNow.AddSeconds(2), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part1", AmbientClock.UtcNow.AddSeconds(2), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), new StatusResults(null, "/Target2", AmbientClock.UtcNow.AddSeconds(3), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part2", AmbientClock.UtcNow.AddSeconds(3), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), new StatusResults(null, "/Target3", AmbientClock.UtcNow.AddSeconds(1), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part3", AmbientClock.UtcNow.AddSeconds(1), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), }); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); StatusResults source3Root = new StatusResults(null, null, AmbientClock.UtcNow, 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHeterogenous, new StatusResults[] { new StatusResults(null, "/Target1", AmbientClock.UtcNow.AddSeconds(1), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part1", AmbientClock.UtcNow.AddSeconds(1), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), new StatusResults(null, "/Target2", AmbientClock.UtcNow.AddSeconds(3), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part2", AmbientClock.UtcNow.AddSeconds(3), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), new StatusResults(null, "/Target3", AmbientClock.UtcNow.AddSeconds(2), 0, Array.Empty <StatusProperty>(), StatusNatureOfSystem.ChildrenHomogenous, new StatusResults[] { new StatusResults(null, "Part3", AmbientClock.UtcNow.AddSeconds(2), 0, new StatusProperty[] { new StatusProperty("Att1", "Val1.0"), new StatusProperty("Att2", "Val2.0") }, StatusNatureOfSystem.Leaf, Array.Empty <StatusResults>()) }), }); organizer.Add(organizer, source1Root); organizer.Add(organizer, source2Root); organizer.Add(organizer, source3Root); organizer.ComputeOverallRatingAndSort(); StatusPropertyRange worstRange = organizer.Children.First().WorstPropertyRange; o = organizer.Children.First().ToString(); } }
public async Task StatusAuditorHistory() { BasicAmbientSettingsSet settings = new BasicAmbientSettingsSet(nameof(StatusAuditorHistory)); settings.ChangeSetting(nameof(StatusChecker) + "-HistoryRetentionMinutes", "5"); settings.ChangeSetting(nameof(StatusChecker) + "-HistoryRetentionEntries", "10"); using (ScopedLocalServiceOverride <IAmbientSettingsSet> localOverrideTest = new ScopedLocalServiceOverride <IAmbientSettingsSet>(settings)) using (AmbientClock.Pause()) { using (StatusAuditorTest test = new StatusAuditorTest(nameof(StatusAuditorTest))) { StatusResults results = await test.GetStatus(); Assert.AreEqual("StatusAuditorTest", test.TargetSystem); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); // since we're rotating the status rating, the frequency will vary because of that Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); // this one starts kicking out history items due to count (this was determined by simply trying it out, but that part doesn't matter for this test) Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); // this one should start kicking history items out due to time Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(30)); Assert.IsTrue(test.History.Count() <= 10); Assert.IsTrue(test.History.First().Time >= AmbientClock.UtcNow.AddMinutes(-5)); } } }
public void AmbientServiceProfilerCoordinatorSettingsNonCurrent() { string system1 = "DynamoDB/Table:My-table/Partition:342644/Result:Success"; string system2 = "S3/Bucket:My-bucket/Prefix:abcdefg/Result:Retry"; string system3 = "SQL/Database:My-database/Table:User/Result:Failed"; BasicAmbientSettingsSet settingsSet = new BasicAmbientSettingsSet(nameof(AmbientServiceProfilerCoordinatorSettingsNonCurrent)); settingsSet.ChangeSetting(nameof(AmbientServiceProfilerCoordinator) + "-DefaultSystemGroupTransform", "(?:([^:/]+)(?:(/Database:[^:/]*)|(/Bucket:[^:/]*)|(/Result:[^:/]*)|(?:/[^/]*))*)"); using (ScopedLocalServiceOverride <IAmbientSettingsSet> o = new ScopedLocalServiceOverride <IAmbientSettingsSet>(settingsSet)) using (ScopedLocalServiceOverride <IAmbientServiceProfiler> p = new ScopedLocalServiceOverride <IAmbientServiceProfiler>(new BasicAmbientServiceProfiler())) using (AmbientClock.Pause()) using (AmbientServiceProfilerCoordinator coordinator = new AmbientServiceProfilerCoordinator()) using (IAmbientServiceProfile scopeProfile = coordinator.CreateCallContextProfiler(nameof(ServiceProfilerBasic))) { _ServiceProfiler.Local?.SwitchSystem(system1); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(5)); _ServiceProfiler.Local?.SwitchSystem(system2); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(200)); _ServiceProfiler.Local?.SwitchSystem(system3); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(3000)); _ServiceProfiler.Local?.SwitchSystem(system1); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(5)); _ServiceProfiler.Local?.SwitchSystem("noreport"); if (scopeProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in scopeProfile.ProfilerStatistics) { if (stats.Group.StartsWith("DynamoDB")) { Assert.AreEqual("DynamoDB/Result:Success", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(10), stats.TimeUsed); Assert.AreEqual(2, stats.ExecutionCount); } else if (stats.Group.StartsWith("S3")) { Assert.AreEqual("S3/Bucket:My-bucket/Result:Retry", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(200), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } else if (stats.Group.StartsWith("SQL")) { Assert.AreEqual("SQL/Database:My-database/Result:Failed", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(3000), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } } } } }
public void Cancellation() { IAmbientProgress progress = AmbientProgressService.Progress; progress?.ResetCancellation(); // make a new cancellation in case the source was canceled in this execution context during a previous test using (AmbientClock.Pause()) { progress?.ResetCancellation(TimeSpan.FromMilliseconds(100)); AmbientCancellationTokenSource tokenSource = progress?.CancellationTokenSource; Assert.IsNotNull(tokenSource); Assert.IsFalse(tokenSource?.IsCancellationRequested ?? true); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); Assert.IsTrue(tokenSource?.IsCancellationRequested ?? false); Assert.ThrowsException <OperationCanceledException>(() => AmbientProgressService.Progress?.ThrowIfCancelled()); } }
public void ServiceProfilerCloseSampleWithRepeat() { using (ScopedLocalServiceOverride <IAmbientServiceProfiler> o = new ScopedLocalServiceOverride <IAmbientServiceProfiler>(new BasicAmbientServiceProfiler())) using (AmbientClock.Pause()) using (AmbientServiceProfilerCoordinator coordinator = new AmbientServiceProfilerCoordinator()) using (IDisposable timeWindowProfile = coordinator.CreateTimeWindowProfiler(nameof(ServiceProfilerCloseSampleWithRepeat), TimeSpan.FromMilliseconds(100), p => Task.CompletedTask)) { AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); // this should trigger the first window and it should have only the default "" entry _ServiceProfiler.Local?.SwitchSystem(nameof(ServiceProfilerCloseSampleWithRepeat) + "1"); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(10)); _ServiceProfiler.Local?.SwitchSystem(null); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(10)); _ServiceProfiler.Local?.SwitchSystem("ServiceProfilerCloseSampleWithRepeat1"); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(80)); // this should trigger the second window, which should close with an augmentation of the first ServiceProfilerCloseSampleWithRepeat1 entry _ServiceProfiler.Local?.SwitchSystem(null); } }
public async Task TestCancellation() { // this first part *should* get cancelled because we're using the system clock AmbientCancellationTokenSource cts = new AmbientCancellationTokenSource(TimeSpan.FromSeconds(1)); await Assert.ThrowsExceptionAsync <OperationCanceledException>(() => AsyncFunctionThatShouldCancelAfterOneSecond(cts.Token)); // switch the current call context to the artifically-paused ambient clock and try again using (AmbientClock.Pause()) { AmbientCancellationTokenSource cts2 = new AmbientCancellationTokenSource(TimeSpan.FromSeconds(1)); // this should *not* throw because the clock has been paused await AsyncFunctionThatShouldCancelAfterOneSecond(cts2.Token); // this skips the artifical paused clock ahead, raising the cancellation AmbientClock.SkipAhead(TimeSpan.FromSeconds(1)); // make sure the cancellation got raised Assert.ThrowsException <OperationCanceledException>(() => cts2.Token.ThrowIfCancellationRequested()); } }
public async Task CacheRefresh() { AmbientSettingsOverride localSettingsSet = new AmbientSettingsOverride(TestCacheSettingsDictionary, nameof(CacheRefresh)); using (AmbientClock.Pause()) using (new ScopedLocalServiceOverride <IAmbientSettingsSet>(localSettingsSet)) { TestCache ret; IAmbientCache cache = new BasicAmbientCache(localSettingsSet); await cache.Store <TestCache>(true, "CacheRefresh1", this, TimeSpan.FromSeconds(1)); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(1100)); ret = await cache.Retrieve <TestCache>("CacheRefresh1", null); Assert.IsNull(ret); await cache.Store <TestCache>(true, "CacheRefresh1", this, TimeSpan.FromMinutes(10)); ret = await cache.Retrieve <TestCache>("CacheRefresh1", null); Assert.AreEqual(this, ret); await Eject(cache, 1); await cache.Store <TestCache>(true, "CacheRefresh2", this); ret = await cache.Retrieve <TestCache>("CacheRefresh2", null); Assert.AreEqual(this, ret); await cache.Store <TestCache>(true, "CacheRefresh3", this); ret = await cache.Retrieve <TestCache>("CacheRefresh3", null); Assert.AreEqual(this, ret); await cache.Remove <TestCache>(true, "CacheRefresh3"); ret = await cache.Retrieve <TestCache>("CacheRefresh3", null); Assert.IsNull(ret); await Eject(cache, 1); } }
public async Task StatusAuditor() { using (AmbientClock.Pause()) { using (StatusAuditorTest test = new StatusAuditorTest(nameof(StatusAuditorTest))) { StatusResults results = await test.GetStatus(); Assert.AreEqual("StatusAuditorTest", test.TargetSystem); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); // each of these skips should trigger another audit, with rotating values AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); AmbientClock.SkipAhead(TimeSpan.FromSeconds(10)); } } }
public void SubProgressCancellationTokenSource() { IAmbientProgress progress = AmbientProgressService.Progress; progress?.ResetCancellation(); // make a new cancellation in case the source was canceled in this execution context during a previous test using (progress?.TrackPart(0.0f, 1.0f)) { IAmbientProgress subprogress = AmbientProgressService.Progress; using (AmbientClock.Pause()) { subprogress?.ResetCancellation(TimeSpan.FromMilliseconds(100)); AmbientCancellationTokenSource tokenSource = subprogress?.CancellationTokenSource; Assert.IsNotNull(tokenSource); Assert.IsFalse(tokenSource?.IsCancellationRequested ?? true); Assert.AreEqual(tokenSource?.Token, subprogress?.CancellationToken); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); Assert.IsTrue(tokenSource?.IsCancellationRequested ?? false); Assert.AreEqual(tokenSource?.Token, subprogress?.CancellationToken); Assert.IsTrue(subprogress?.CancellationToken.IsCancellationRequested ?? false); subprogress?.ResetCancellation(null); AmbientCancellationTokenSource newTokenSource = subprogress?.CancellationTokenSource; Assert.IsNotNull(newTokenSource); Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true); Assert.AreEqual(newTokenSource?.Token, subprogress?.CancellationToken); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true); Assert.IsTrue(newTokenSource?.Token.CanBeCanceled ?? false); Assert.AreEqual(newTokenSource?.Token, subprogress?.CancellationToken); Assert.IsFalse(subprogress?.CancellationToken.IsCancellationRequested ?? true); subprogress?.Update(0.5f); subprogress?.ThrowIfCancelled(); } } }
public void ServiceProfilerBasic() { using (ScopedLocalServiceOverride <IAmbientServiceProfiler> o = new ScopedLocalServiceOverride <IAmbientServiceProfiler>(new BasicAmbientServiceProfiler())) using (AmbientClock.Pause()) using (AmbientServiceProfilerCoordinator coordinator = new AmbientServiceProfilerCoordinator()) using (IAmbientServiceProfile processProfile = coordinator.CreateProcessProfiler(nameof(ServiceProfilerBasic))) using (IDisposable timeWindowProfile = coordinator.CreateTimeWindowProfiler(nameof(ServiceProfilerBasic), TimeSpan.FromMilliseconds(100), p => Task.CompletedTask)) using (IAmbientServiceProfile scopeProfile = coordinator.CreateCallContextProfiler(nameof(ServiceProfilerBasic))) { _ServiceProfiler.Local?.SwitchSystem("ServiceProfilerBasic1"); Assert.AreEqual(nameof(ServiceProfilerBasic), processProfile?.ScopeName); if (processProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in processProfile.ProfilerStatistics) { if (string.IsNullOrEmpty(stats.Group)) { Assert.AreEqual("", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(0, stats.TotalStopwatchTicksUsed); } else { Assert.AreEqual("ServiceProfilerBasic1", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(0, stats.TotalStopwatchTicksUsed); } } } Assert.AreEqual(nameof(ServiceProfilerBasic), scopeProfile?.ScopeName); if (scopeProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in scopeProfile.ProfilerStatistics) { if (string.IsNullOrEmpty(stats.Group)) { Assert.AreEqual("", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(0, stats.TotalStopwatchTicksUsed); } else { Assert.AreEqual("ServiceProfilerBasic1", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(0, stats.TotalStopwatchTicksUsed); } } } AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); _ServiceProfiler.Local?.SwitchSystem(null); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(113)); _ServiceProfiler.Local?.SwitchSystem("ServiceProfilerBasic2"); if (scopeProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in scopeProfile.ProfilerStatistics) { if (string.IsNullOrEmpty(stats.Group)) { Assert.AreEqual("", stats.Group); Assert.AreEqual(2, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(113), stats.TimeUsed); } else if (stats.Group.EndsWith("1")) { Assert.AreEqual("ServiceProfilerBasic1", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(100), stats.TimeUsed); } else if (stats.Group.EndsWith("2")) { Assert.AreEqual("ServiceProfilerBasic2", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(0), stats.TimeUsed); } } } AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); _ServiceProfiler.Local?.SwitchSystem(null); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(113)); _ServiceProfiler.Local?.SwitchSystem("ServiceProfilerBasic3"); if (scopeProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in scopeProfile.ProfilerStatistics) { if (string.IsNullOrEmpty(stats.Group)) { Assert.AreEqual("", stats.Group); Assert.AreEqual(3, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(226), stats.TimeUsed); } else if (stats.Group.EndsWith("1")) { Assert.AreEqual("ServiceProfilerBasic1", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(100), stats.TimeUsed); } else if (stats.Group.EndsWith("2")) { Assert.AreEqual("ServiceProfilerBasic2", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(100), stats.TimeUsed); } else if (stats.Group.EndsWith("3")) { Assert.AreEqual("ServiceProfilerBasic3", stats.Group); Assert.AreEqual(1, stats.ExecutionCount); Assert.AreEqual(TimeSpan.FromMilliseconds(0), stats.TimeUsed); } } } _ServiceProfiler.Local?.SwitchSystem(null); } }
public async Task CacheDoubleExpiration() { IAmbientCache localOverride = new BasicAmbientCache(); using (AmbientClock.Pause()) using (ScopedLocalServiceOverride <IAmbientCache> localCache = new ScopedLocalServiceOverride <IAmbientCache>(localOverride)) { string keyName1 = nameof(CacheDoubleExpiration) + "1"; string keyName2 = nameof(CacheDoubleExpiration) + "2"; string keyName3 = nameof(CacheDoubleExpiration) + "3"; string keyName4 = nameof(CacheDoubleExpiration) + "4"; string keyName5 = nameof(CacheDoubleExpiration) + "5"; // string keyName6 = nameof(CacheDoubleExpiration) + "6"; TestCache ret; AmbientCache <TestCache> cache = new AmbientCache <TestCache>(); await cache.Store(true, keyName1, this, TimeSpan.FromMilliseconds(51)); await cache.Store(true, keyName2, this, TimeSpan.FromMilliseconds(50)); await cache.Store(true, keyName3, this, TimeSpan.FromSeconds(50)); await cache.Store(true, keyName4, this, TimeSpan.FromSeconds(50)); await cache.Store(true, keyName5, this, TimeSpan.FromSeconds(50)); // await cache.Store(true, keyName6, this, TimeSpan.FromSeconds(50)); ret = await cache.Retrieve <TestCache>(keyName2); Assert.IsNotNull(ret); await Eject(cache, 1); // this should eject 1 because it's the LRU item ret = await cache.Retrieve <TestCache>(keyName2); Assert.IsNotNull(ret); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); ret = await cache.Retrieve <TestCache>(keyName1); // this should return null even though we haven't ejected stuff because it's expired Assert.IsNull(ret); await Eject(cache, 2); // this should eject 2 because it's both expired, and 3 because it's the LRU item ret = await cache.Retrieve <TestCache>(keyName1); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName2); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName3); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName4); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName5); Assert.IsNotNull(ret); //ret = await cache.Retrieve<TestCache>(keyName6); //Assert.IsNotNull(ret); await Eject(cache, 1); // this should eject 4, but only because it's the LRU item ret = await cache.Retrieve <TestCache>(keyName4); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName5); Assert.IsNotNull(ret); //ret = await cache.Retrieve<TestCache>(keyName6); //Assert.IsNotNull(ret); } }
public async Task CacheSkipAndEmptyEject() { AmbientSettingsOverride localSettingsSet = new AmbientSettingsOverride(AllowEmptyCacheSettingsDictionary, nameof(CacheAmbient)); using (AmbientClock.Pause()) using (new ScopedLocalServiceOverride <IAmbientSettingsSet>(localSettingsSet)) { IAmbientCache localOverride = new BasicAmbientCache(); using (ScopedLocalServiceOverride <IAmbientCache> localCache = new ScopedLocalServiceOverride <IAmbientCache>(localOverride)) { string keyName1 = nameof(CacheExpiration) + "1"; string keyName2 = nameof(CacheExpiration) + "2"; string keyName3 = nameof(CacheExpiration) + "3"; //string keyName4 = nameof(CacheExpiration) + "4"; //string keyName5 = nameof(CacheExpiration) + "5"; //string keyName6 = nameof(CacheExpiration) + "6"; //string keyName7 = nameof(CacheExpiration) + "7"; TestCache ret; AmbientCache <TestCache> cache = new AmbientCache <TestCache>(); await cache.Store(true, keyName1, this, TimeSpan.FromMilliseconds(100)); await cache.Store(true, keyName2, this, TimeSpan.FromMilliseconds(50)); await cache.Store(true, keyName3, this, TimeSpan.FromMilliseconds(100)); ret = await cache.Retrieve <TestCache>(keyName1); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName2, TimeSpan.FromMilliseconds(100)); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName3); Assert.IsNotNull(ret); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(50)); await Eject(cache, 1); // this should eject 1 because it's the LRU timed, and the first timed entry for 2 because that's expired, but 2 should remain with a refreshed entry ret = await cache.Retrieve <TestCache>(keyName1); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName2, TimeSpan.FromMilliseconds(100)); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName3); Assert.IsNotNull(ret); await Eject(cache, 1); // this should skip 2 because it's bee refershed again and eject 3 because it's the LRU timed ret = await cache.Retrieve <TestCache>(keyName1); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName2); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName3); Assert.IsNull(ret); // change key2 to be untimed await cache.Store(true, keyName2, this); await Eject(cache, 1); // this should skip over the timed entry for 2 but then eject it because it is untimed } } }
public async Task CacheExpiration() { IAmbientCache localOverride = new BasicAmbientCache(); using (AmbientClock.Pause()) using (ScopedLocalServiceOverride <IAmbientCache> localCache = new ScopedLocalServiceOverride <IAmbientCache>(localOverride)) { string keyName1 = nameof(CacheExpiration) + "1"; string keyName2 = nameof(CacheExpiration) + "2"; string keyName3 = nameof(CacheExpiration) + "3"; string keyName4 = nameof(CacheExpiration) + "4"; string keyName5 = nameof(CacheExpiration) + "5"; string keyName6 = nameof(CacheExpiration) + "6"; string keyName7 = nameof(CacheExpiration) + "7"; TestCache ret; AmbientCache <TestCache> cache = new AmbientCache <TestCache>(); await cache.Store(true, keyName1, this, TimeSpan.FromMilliseconds(50)); await cache.Store(true, keyName1, this, TimeSpan.FromMilliseconds(51)); await cache.Store(true, keyName2, this); await cache.Store(true, keyName2, this); await cache.Store(true, keyName3, this, TimeSpan.FromMilliseconds(-51)); // this should never get cached because the time span is negative await cache.Store(true, keyName3, this, TimeSpan.FromMilliseconds(-50)); // this should never get cached because the time span is negative await cache.Store(true, keyName4, this); await cache.Store(true, keyName4, this); await cache.Store(true, keyName5, this, TimeSpan.FromMilliseconds(50)); await cache.Store(true, keyName5, this, TimeSpan.FromMilliseconds(50)); await cache.Store(true, keyName6, this, TimeSpan.FromMilliseconds(1000)); await cache.Store(true, keyName6, this, TimeSpan.FromMilliseconds(1000)); await cache.Store(true, keyName7, this, TimeSpan.FromMilliseconds(75)); await cache.Store(true, keyName7, this, TimeSpan.FromMilliseconds(1000)); ret = await cache.Retrieve <TestCache>(keyName1); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName2); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName3); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName4); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName5); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName6); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName7); Assert.IsNotNull(ret); await Eject(cache, 1); // this should eject 1 because it's the LRU timed and 2 because it's the LRU untimed ret = await cache.Retrieve <TestCache>(keyName1); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName2); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName4); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName5); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName6); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName7); Assert.IsNotNull(ret); await Eject(cache, 1); // this should eject 5 because it's the LRU timed and 4 because it's the LRU untimed ret = await cache.Retrieve <TestCache>(keyName4); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName5); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName6); Assert.IsNotNull(ret); ret = await cache.Retrieve <TestCache>(keyName7); Assert.IsNotNull(ret); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); await Eject(cache, 1); // this should eject 6 because it's the LRU timed but not 7 because only the first entry is expired, and not untimed LRU ret = await cache.Retrieve <TestCache>(keyName6); Assert.IsNull(ret); ret = await cache.Retrieve <TestCache>(keyName7); Assert.IsNotNull(ret); } }
public async Task AmbientFileLoggerFileRotation() { string logFilePrefix = null; try { using (AmbientClock.Pause()) using (AmbientFileLogger logger = new AmbientFileLogger(null, null, 8 * 60)) { logFilePrefix = logger.FilePrefix; // delete any preexisting files await AmbientFileLogger.TryDeleteAllFiles(logFilePrefix); using (IDisposable over = Logger.ScopedLocalOverride(logger)) { // log the first test message (this will cause the file to be created, but only *after* this message gets flushed Logger.Local?.Log("test1"); Assert.AreEqual(0, TempFileCount(logFilePrefix)); if (Logger.Local != null) { await Logger.Local.Flush(); } Assert.AreEqual(1, TempFileCount(logFilePrefix)); // get the name of the first log file string firstLogFile = logger.GetLogFileName(AmbientClock.UtcNow); // skip ahead eight hours and flush another message (it should go in another file) AmbientClock.SkipAhead(TimeSpan.FromHours(8)); // log the second test message Logger.Local?.Log("test2"); if (Logger.Local != null) { await Logger.Local.Flush(); } Assert.AreEqual(2, TempFileCount(logFilePrefix)); // skip ahead eight hours and flush another message (it should go in another file) AmbientClock.SkipAhead(TimeSpan.FromHours(8)); // log the third test message Logger.Local?.Log("test3"); if (Logger.Local != null) { await Logger.Local.Flush(); } Assert.AreEqual(3, TempFileCount(logFilePrefix)); // skip ahead eight hours and flush another message (this should rotate around to the first file) AmbientClock.SkipAhead(TimeSpan.FromHours(8)); // log the fourth test message Logger.Local?.Log("test4"); if (Logger.Local != null) { await Logger.Local.Flush(); } Assert.AreEqual(3, TempFileCount(logFilePrefix)); // skip ahead eight hours and flush another message (this should rotate around to the second file) AmbientClock.SkipAhead(TimeSpan.FromHours(8)); // log a fifth test message just to make sure the first file gets closed Logger.Local?.Log("test5"); if (Logger.Local != null) { await Logger.Local.Flush(); } Assert.AreEqual(3, TempFileCount(logFilePrefix)); // open the first log file string firstLogContents = File.ReadAllText(firstLogFile); Assert.IsFalse(firstLogContents.Contains("test1")); // the first log message should have been overwritten when the log rotated around to the first file again Assert.IsTrue(firstLogContents.Contains("test4")); // try to delete files here (this will cause an ignored exception) await AmbientFileLogger.TryDeleteAllFiles(logFilePrefix); } // dispose a little early so we can test flushing after disposal logger.Dispose(); await logger.Flush(); // this should just be ignored after disposal } } finally { await AmbientFileLogger.TryDeleteAllFiles(logFilePrefix !); } }
public async Task StatusClass() { await Status.DefaultInstance.Start(); Assert.IsFalse(Status.DefaultInstance.ShuttingDown); try { DateTime start = AmbientClock.UtcNow; await Status.DefaultInstance.RefreshAsync(); StatusResults overallStatus = Status.DefaultInstance.Results; Assert.AreEqual("/", overallStatus.TargetSystem); Assert.AreEqual(0, overallStatus.RelativeDetailLevel); Assert.AreEqual(StatusNatureOfSystem.ChildrenHeterogenous, overallStatus.NatureOfSystem); Assert.AreEqual(0, overallStatus.Properties.Count()); Assert.IsTrue(overallStatus.Children.Count() > 0); Assert.IsFalse(string.IsNullOrEmpty(overallStatus.ToString())); StatusResults sampleDisk = overallStatus.Children.FirstOrDefault(c => c.TargetSystem == "SampleDisk" && c.Children.Any()) as StatusResults; Assert.IsNotNull(sampleDisk); StatusResults disk = sampleDisk !.Children.FirstOrDefault() as StatusResults; Assert.IsNotNull(disk); Assert.IsTrue(disk !.Properties.Count() > 0); // the properties in the node itself are the constant properties, ie. the path for a disk test Assert.IsFalse(string.IsNullOrEmpty(sampleDisk !.ToString())); StatusProperty att = disk.Properties.FirstOrDefault(a => a.Name == "TotalBytes"); Assert.IsNotNull(att); Assert.IsFalse(string.IsNullOrEmpty(att !.ToString())); Assert.IsFalse(String.IsNullOrEmpty(att !.Name)); Assert.IsFalse(String.IsNullOrEmpty(att !.Value)); HashSet <StatusResults> test = new HashSet <StatusResults>(); StatusResults c1 = overallStatus.Children.FirstOrDefault(c => c.TargetSystem == nameof(TestHeterogenousExplicitRating)); Assert.IsNotNull(c1); Assert.IsNotNull(c1 !.Report); Assert.IsNotNull(c1 !.Report?.Alert?.Rating); Assert.IsFalse(string.IsNullOrEmpty(c1 !.ToString())); test.Add(c1); StatusResults c2 = overallStatus.Children.FirstOrDefault(c => c.TargetSystem == nameof(TestHomogeneousExplicitFailure)); Assert.IsNotNull(c2); Assert.IsNotNull(c2 !.Report); Assert.IsNotNull(c2 !.Report?.Alert?.Rating); Assert.AreNotEqual(c1 !.Report?.Alert, c2 !.Report?.Alert); Assert.IsFalse(string.IsNullOrEmpty(c2 !.ToString())); test.Add(c2); StatusResults c3 = overallStatus.Children.FirstOrDefault(c => c.TargetSystem == nameof(TestMachineConstantStatus)); Assert.IsNotNull(c3); Assert.IsNull(c3 !.Report); Assert.IsFalse(string.IsNullOrEmpty(c3 !.ToString())); test.Add(c3); StatusAuditAlert auditResult = overallStatus.GetSummaryAlerts(true, StatusRating.Alert, false); Assert.AreEqual(0, overallStatus.Properties.Count()); HashSet <StatusAuditReport> test3 = new HashSet <StatusAuditReport>(); Assert.IsTrue(auditResult.Rating >= -1.0f && auditResult.Rating <= 4.0f); Assert.IsFalse(string.IsNullOrEmpty(auditResult.Terse)); Assert.IsFalse(string.IsNullOrEmpty(auditResult.Details)); Assert.IsTrue(overallStatus.SourceSystem == null); Assert.IsTrue(auditResult.Rating <= StatusRating.Fail); Assert.IsFalse(string.IsNullOrEmpty(auditResult.ToString())); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); await Status.DefaultInstance.RefreshAsync(); overallStatus = Status.DefaultInstance.Results; StatusAuditAlert notOkayResult = overallStatus.GetSummaryAlerts(true, StatusRating.Okay, false); StatusAuditAlert fullResult = overallStatus.GetSummaryAlerts(true, float.MaxValue, false); StatusAuditAlert overallSummaryAlerts = Status.DefaultInstance.Summary; Assert.IsTrue(overallSummaryAlerts.Rating <StatusRating.Fail && overallSummaryAlerts.Rating> StatusRating.Catastrophic); StatusAuditAlert overallSummaryAlertsAndFailures = Status.DefaultInstance.SummaryAlertsAndFailures; Assert.IsTrue(overallSummaryAlertsAndFailures.Rating <StatusRating.Fail && overallSummaryAlertsAndFailures.Rating> StatusRating.Catastrophic); StatusAuditAlert overallSummaryFailures = Status.DefaultInstance.SummaryFailures; Assert.IsTrue(overallSummaryFailures.Rating <StatusRating.Fail && overallSummaryFailures.Rating> StatusRating.Catastrophic); } finally { await Status.DefaultInstance.Stop(); } }
public void AmbientServiceProfilerCoordinatorOverrideGroupTransform() { string system1Start = "DynamoDB/Table:My-table/Partition:342644"; string system1End = "DynamoDB/Table:My-table/Partition:342644/Result:Success"; string system2 = "S3/Bucket:My-bucket/Prefix:abcdefg/Result:Retry"; string system3 = "SQL/Database:My-database/Table:User/Result:Failed"; string groupTransform = "(?:([^:/]+)(?:(/Database:[^:/]*)|(/Bucket:[^:/]*)|(/Result:[^:/]*)|(?:/[^/]*))*)"; IAmbientServiceProfile timeWindowProfile = null; using (AmbientClock.Pause()) using (ScopedLocalServiceOverride <IAmbientServiceProfiler> o = new ScopedLocalServiceOverride <IAmbientServiceProfiler>(new BasicAmbientServiceProfiler())) using (AmbientServiceProfilerCoordinator coordinator = new AmbientServiceProfilerCoordinator()) using (IAmbientServiceProfile processProfile = coordinator.CreateProcessProfiler(nameof(AmbientServiceProfilerCoordinatorOverrideGroupTransform), groupTransform)) using (IDisposable timeWindowProfiler = coordinator.CreateTimeWindowProfiler(nameof(AmbientServiceProfilerCoordinatorOverrideGroupTransform), TimeSpan.FromMilliseconds(10000), p => { timeWindowProfile = p; return(Task.CompletedTask); }, groupTransform)) using (IAmbientServiceProfile scopeProfile = coordinator.CreateCallContextProfiler(nameof(AmbientServiceProfilerCoordinatorOverrideGroupTransform), groupTransform)) { _ServiceProfiler.Local?.SwitchSystem(system1Start); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(5)); _ServiceProfiler.Local?.SwitchSystem(system2, system1End); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(200)); _ServiceProfiler.Local?.SwitchSystem(system3); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(3000)); _ServiceProfiler.Local?.SwitchSystem(system1End); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(5)); _ServiceProfiler.Local?.SwitchSystem("noreport"); if (scopeProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in scopeProfile.ProfilerStatistics) { if (stats.Group.StartsWith("DynamoDB")) { Assert.AreEqual("DynamoDB/Result:Success", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(10), stats.TimeUsed); Assert.AreEqual(2, stats.ExecutionCount); } else if (stats.Group.StartsWith("S3")) { Assert.AreEqual("S3/Bucket:My-bucket/Result:Retry", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(200), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } else if (stats.Group.StartsWith("SQL")) { Assert.AreEqual("SQL/Database:My-database/Result:Failed", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(3000), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } } } if (processProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in processProfile.ProfilerStatistics) { if (stats.Group.StartsWith("DynamoDB")) { Assert.AreEqual("DynamoDB/Result:Success", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(10), stats.TimeUsed); Assert.AreEqual(2, stats.ExecutionCount); } else if (stats.Group.StartsWith("S3")) { Assert.AreEqual("S3/Bucket:My-bucket/Result:Retry", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(200), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } else if (stats.Group.StartsWith("SQL")) { Assert.AreEqual("SQL/Database:My-database/Result:Failed", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(3000), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } } } AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(10000)); if (timeWindowProfile != null) { foreach (AmbientServiceProfilerAccumulator stats in timeWindowProfile.ProfilerStatistics) { if (stats.Group.StartsWith("DynamoDB")) { Assert.AreEqual("DynamoDB/Result:Success", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(10), stats.TimeUsed); Assert.AreEqual(2, stats.ExecutionCount); } else if (stats.Group.StartsWith("S3")) { Assert.AreEqual("S3/Bucket:My-bucket/Result:Retry", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(200), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } else if (stats.Group.StartsWith("SQL")) { Assert.AreEqual("SQL/Database:My-database/Result:Failed", stats.Group); Assert.AreEqual(TimeSpan.FromMilliseconds(3000), stats.TimeUsed); Assert.AreEqual(1, stats.ExecutionCount); } } } } }
public void CancellationTokenSource() { IAmbientProgress progress = AmbientProgressService.Progress; progress?.ResetCancellation(); // make a new cancellation in case the source was canceled in this execution context during a previous test using (AmbientClock.Pause()) { progress?.ResetCancellation(TimeSpan.FromMilliseconds(102)); using (AmbientCancellationTokenSource tokenSource = progress?.CancellationTokenSource) { Assert.IsNotNull(tokenSource); Assert.IsFalse(tokenSource?.IsCancellationRequested ?? true); Assert.AreEqual(tokenSource?.Token, progress?.CancellationToken); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(111)); Assert.IsTrue(tokenSource?.IsCancellationRequested ?? false); Assert.AreEqual(tokenSource?.Token, progress?.CancellationToken); Assert.IsTrue(progress?.CancellationToken.IsCancellationRequested ?? false); progress?.ResetCancellation(); AmbientCancellationTokenSource newTokenSource = progress?.CancellationTokenSource; Assert.IsNotNull(newTokenSource); Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true); Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100)); Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true); Assert.IsTrue(newTokenSource?.Token.CanBeCanceled ?? false); Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken); Assert.IsFalse(progress?.CancellationToken.IsCancellationRequested ?? true); progress?.Update(0.5f); progress?.ThrowIfCancelled(); using (CancellationTokenSource ts = new CancellationTokenSource()) { progress?.ResetCancellation(ts); newTokenSource = progress?.CancellationTokenSource; Assert.IsNotNull(newTokenSource); Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true); Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken); Assert.IsTrue(newTokenSource?.Token.CanBeCanceled ?? false); ts.Cancel(); Assert.IsTrue(newTokenSource?.IsCancellationRequested ?? false); Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken); Assert.IsTrue(progress?.CancellationToken.IsCancellationRequested ?? false); } using (AmbientCancellationTokenSource ts = new AmbientCancellationTokenSource(null, null)) { Assert.IsFalse(ts.IsCancellationRequested); Assert.IsFalse(ts.Token.IsCancellationRequested); ts.Dispose(); Assert.IsTrue(ts.IsCancellationRequested); Assert.IsTrue(ts.Token.IsCancellationRequested); } using (AmbientCancellationTokenSource ts = new AmbientCancellationTokenSource(null, TimeSpan.FromMilliseconds(int.MaxValue))) { Assert.IsFalse(ts.IsCancellationRequested); // theoretically, this could fail if this part of the test takes more than 30 days to execute Assert.IsFalse(ts.Token.IsCancellationRequested); ts.Dispose(); Assert.IsTrue(ts.IsCancellationRequested); Assert.IsTrue(ts.Token.IsCancellationRequested); } AmbientCancellationTokenSource dispose; using (AmbientCancellationTokenSource ts = new AmbientCancellationTokenSource()) { dispose = ts; } dispose.CancelAfter(1); System.Threading.Thread.Sleep(500); AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(500)); dispose.Cancel(false); } } }