public IEnumerable<FeaturedMovies> GetFeaturedMovies(out IChangeToken expirationToken) { _featuredMoviesTokenSource = new CancellationTokenSource(); expirationToken = new CancellationChangeToken(_featuredMoviesTokenSource.Token); return GetMovies().OrderBy(m => m.Rank).Take(2); }
public void RegisteredCallbacks_AreInvokedExactlyOnce() { // Arrange var firstCancellationTokenSource = new CancellationTokenSource(); var secondCancellationTokenSource = new CancellationTokenSource(); var thirdCancellationTokenSource = new CancellationTokenSource(); var firstCancellationToken = firstCancellationTokenSource.Token; var secondCancellationToken = secondCancellationTokenSource.Token; var thirdCancellationToken = thirdCancellationTokenSource.Token; var firstCancellationChangeToken = new CancellationChangeToken(firstCancellationToken); var secondCancellationChangeToken = new CancellationChangeToken(secondCancellationToken); var thirdCancellationChangeToken = new CancellationChangeToken(thirdCancellationToken); var compositeChangeToken = new CompositeChangeToken(new List <IChangeToken> { firstCancellationChangeToken, secondCancellationChangeToken, thirdCancellationChangeToken }); var count1 = 0; var count2 = 0; compositeChangeToken.RegisterChangeCallback(_ => count1++, null); compositeChangeToken.RegisterChangeCallback(_ => count2++, null); // Act firstCancellationTokenSource.Cancel(); secondCancellationTokenSource.Cancel(); // Assert Assert.Equal(1, count1); Assert.Equal(1, count2); }
public void AsyncLocalsNotCapturedAndRestored() { // Capture clean context var executionContext = ExecutionContext.Capture(); var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; var cancellationChangeToken = new CancellationChangeToken(cancellationToken); var executed = false; // Set AsyncLocal var asyncLocal = new AsyncLocal <int>(); asyncLocal.Value = 1; // Register Callback cancellationChangeToken.RegisterChangeCallback(al => { // AsyncLocal not set, when run on clean context // A suppressed flow runs in current context, rather than restoring the captured context Assert.Equal(0, ((AsyncLocal <int>)al).Value); executed = true; }, asyncLocal); // AsyncLocal should still be set Assert.Equal(1, asyncLocal.Value); // Check AsyncLocal is not restored by running on clean context ExecutionContext.Run(executionContext, cts => ((CancellationTokenSource)cts).Cancel(), cancellationTokenSource); // AsyncLocal should still be set Assert.Equal(1, asyncLocal.Value); Assert.True(executed); }
public IChangeToken GetToken(string key) { return _changeTokens.GetOrAdd( key, _ => { var cancellationTokenSource = new CancellationTokenSource(); var changeToken = new CancellationChangeToken(cancellationTokenSource.Token); return new ChangeTokenInfo(changeToken, cancellationTokenSource); }).ChangeToken; }
public string GetProducts(string category, out IChangeToken changeToken) { var token = _tokenSource.IsCancellationRequested ? CancellationToken.None : _tokenSource.Token; changeToken = new CancellationChangeToken(token); if (category == "Books") { return "Book1, Book2"; } else { return "Laptops"; } }
public string GetCriticsQuote(out IChangeToken expirationToken) { _quotesTokenSource = new CancellationTokenSource(); var quotes = new[] { "A must see for iguana lovers everywhere", "Slightly better than watching paint dry", "Never felt more relieved seeing the credits roll", "Bravo!" }; expirationToken = new CancellationChangeToken(_quotesTokenSource.Token); return quotes[_random.Next(0, quotes.Length)]; }
public async Task RegisteredCallbackGetsInvokedExactlyOnce_WhenMultipleConcurrentChangeEventsOccur() { // Arrange var event1 = new ManualResetEvent(false); var event2 = new ManualResetEvent(false); var event3 = new ManualResetEvent(false); var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; var cancellationChangeToken = new CancellationChangeToken(cancellationToken); var count = 0; Action <object> callback = _ => { count++; event3.Set(); event1.WaitOne(5000); }; var compositeChangeToken = new CompositeChangeToken(new List <IChangeToken> { cancellationChangeToken }); compositeChangeToken.RegisterChangeCallback(callback, null); // Act var firstChange = Task.Run(() => { event2.WaitOne(5000); cancellationTokenSource.Cancel(); }); var secondChange = Task.Run(() => { event3.WaitOne(5000); cancellationTokenSource.Cancel(); event1.Set(); }); event2.Set(); await Task.WhenAll(firstChange, secondChange); // Assert Assert.Equal(1, count); }
public ProxyCancellationChangeToken(CancellationToken cancellationToken, Action disposing) { _cancellationChangeToken = new CancellationChangeToken(cancellationToken); _disposing = disposing; }
public void FindView_InvokesViewLocationExpanders_IfChangeTokenExpires() { // Arrange var cancellationTokenSource = new CancellationTokenSource(); var changeToken = new CancellationChangeToken(cancellationTokenSource.Token); var page = Mock.Of<IRazorPage>(); var pageFactory = new Mock<IRazorPageFactoryProvider>(); pageFactory .Setup(p => p.CreateFactory("viewlocation3")) .Returns(new RazorPageFactoryResult(new[] { changeToken })); var expander = new Mock<IViewLocationExpander>(); var expandedLocations = new[] { "viewlocation1", "viewlocation2", "viewlocation3", }; expander .Setup(v => v.PopulateValues(It.IsAny<ViewLocationExpanderContext>())) .Callback((ViewLocationExpanderContext expanderContext) => { expanderContext.Values["somekey"] = "somevalue"; }) .Verifiable(); expander .Setup(v => v.ExpandViewLocations( It.IsAny<ViewLocationExpanderContext>(), It.IsAny<IEnumerable<string>>())) .Returns(expandedLocations) .Verifiable(); var viewEngine = CreateViewEngine( pageFactory.Object, expanders: new[] { expander.Object }); var context = GetActionContext(_controllerTestContext); // Act - 1 var result = viewEngine.FindView(context, "MyView", isMainPage: true); // Assert - 1 Assert.False(result.Success); Assert.Equal(expandedLocations, result.SearchedLocations); expander.Verify(); // Act - 2 pageFactory .Setup(p => p.CreateFactory("viewlocation3")) .Returns(new RazorPageFactoryResult(() => page, new IChangeToken[0])); cancellationTokenSource.Cancel(); result = viewEngine.FindView(context, "MyView", isMainPage: true); // Assert - 2 Assert.True(result.Success); var view = Assert.IsType<RazorView>(result.View); Assert.Same(page, view.RazorPage); expander.Verify( v => v.PopulateValues(It.IsAny<ViewLocationExpanderContext>()), Times.Exactly(2)); expander.Verify( v => v.ExpandViewLocations(It.IsAny<ViewLocationExpanderContext>(), It.IsAny<IEnumerable<string>>()), Times.Exactly(2)); }
public void FindView_InvokesPageFactoryIfViewStartExpirationTokensHaveExpired() { // Arrange var page1 = Mock.Of<IRazorPage>(); var page2 = Mock.Of<IRazorPage>(); var viewStart = Mock.Of<IRazorPage>(); var sequence = new MockSequence(); var cancellationTokenSource = new CancellationTokenSource(); var changeToken = new CancellationChangeToken(cancellationTokenSource.Token); var pageFactory = new Mock<IRazorPageFactoryProvider>(); pageFactory .InSequence(sequence) .Setup(p => p.CreateFactory("/Views/bar/baz.cshtml")) .Returns(new RazorPageFactoryResult(() => page1, new IChangeToken[0])); pageFactory .InSequence(sequence) .Setup(p => p.CreateFactory("/Views/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(new[] { changeToken })) .Verifiable(); pageFactory .InSequence(sequence) .Setup(p => p.CreateFactory("/Views/bar/baz.cshtml")) .Returns(new RazorPageFactoryResult(() => page2, new IChangeToken[0])); pageFactory .InSequence(sequence) .Setup(p => p.CreateFactory("/Views/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(() => viewStart, new IChangeToken[0])); var viewEngine = CreateViewEngine(pageFactory.Object); var context = GetActionContext(_controllerTestContext); // Act 1 var result1 = viewEngine.FindView(context, "baz", isMainPage: true); // Assert 1 Assert.True(result1.Success); var view1 = Assert.IsType<RazorView>(result1.View); Assert.Same(page1, view1.RazorPage); Assert.Empty(view1.ViewStartPages); // Act 2 cancellationTokenSource.Cancel(); var result2 = viewEngine.FindView(context, "baz", isMainPage: true); // Assert 2 Assert.True(result2.Success); var view2 = Assert.IsType<RazorView>(result2.View); Assert.Same(page2, view2.RazorPage); var actualViewStart = Assert.Single(view2.ViewStartPages); Assert.Equal(viewStart, actualViewStart); pageFactory.Verify(); }
public void FindView_DoesNotExpireCachedResults_IfViewStartsExpire() { // Arrange var pageFactory = new Mock<IRazorPageFactoryProvider>(); var page = Mock.Of<IRazorPage>(); var viewStart = Mock.Of<IRazorPage>(); var cancellationTokenSource = new CancellationTokenSource(); var changeToken = new CancellationChangeToken(cancellationTokenSource.Token); pageFactory .Setup(p => p.CreateFactory("/Views/bar/test-view.cshtml")) .Returns(new RazorPageFactoryResult(() => page, new IChangeToken[0])); pageFactory .Setup(p => p.CreateFactory("/Views/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(() => viewStart, new[] { changeToken })); var viewEngine = CreateViewEngine(pageFactory.Object); var context = GetActionContext(_controllerTestContext); // Act - 1 var result1 = viewEngine.FindView(context, "test-view", isMainPage: false); // Assert - 1 Assert.True(result1.Success); var view1 = Assert.IsType<RazorView>(result1.View); Assert.Same(page, view1.RazorPage); Assert.Equal("test-view", result1.ViewName); Assert.Empty(view1.ViewStartPages); // Act - 2 cancellationTokenSource.Cancel(); var result2 = viewEngine.FindView(context, "test-view", isMainPage: false); // Assert - 2 Assert.True(result2.Success); var view2 = Assert.IsType<RazorView>(result2.View); Assert.Same(page, view2.RazorPage); pageFactory.Verify(p => p.CreateFactory("/Views/bar/test-view.cshtml"), Times.Once()); }