예제 #1
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
 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;
 }
예제 #5
0
 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";
     }
 }
예제 #6
0
        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);
        }
예제 #8
0
 public ProxyCancellationChangeToken(CancellationToken cancellationToken, Action disposing)
 {
     _cancellationChangeToken = new CancellationChangeToken(cancellationToken);
     _disposing = disposing;
 }
예제 #9
0
        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));
        }
예제 #10
0
        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();
        }
예제 #11
0
        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());
        }