コード例 #1
0
        public async Task ProcessAsync_ReturnsCachedValue_IfEnabled()
        {
            // Arrange
            var id               = "unique-id";
            var childContent     = "original-child-content";
            var cache            = new MemoryCache(new MemoryCacheOptions());
            var tagHelperContext = GetTagHelperContext(id);
            var tagHelperOutput  = GetTagHelperOutput(
                attributes: new TagHelperAttributeList(),
                childContent: childContent);
            var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            // Act
            await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);

            // Assert
            Assert.Empty(tagHelperOutput.PreContent.GetContent());
            Assert.Empty(tagHelperOutput.PostContent.GetContent());
            Assert.True(tagHelperOutput.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput.Content.GetContent());
        }
コード例 #2
0
        public async Task ProcessAsync_FlowsEntryLinkThatAllowsAddingTriggersToAddedEntry()
        {
            // Arrange
            var id = "some-id";
            var expectedContent = new DefaultTagHelperContent();

            expectedContent.SetContent("some-content");
            var tokenSource       = new CancellationTokenSource();
            var cache             = new MemoryCache(new MemoryCacheOptions());
            var cacheEntryOptions = new MemoryCacheEntryOptions()
                                    .AddExpirationToken(new CancellationChangeToken(tokenSource.Token));
            var tagHelperContext = new TagHelperContext(
                allAttributes: new TagHelperAttributeList(),
                items: new Dictionary <object, object>(),
                uniqueId: id);
            var tagHelperOutput = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList {
                { "attr", "value" }
            },
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                TagHelperContent tagHelperContent;
                if (!cache.TryGetValue("key1", out tagHelperContent))
                {
                    tagHelperContent = expectedContent;
                    cache.Set("key1", tagHelperContent, cacheEntryOptions);
                }

                return(Task.FromResult(tagHelperContent));
            });

            tagHelperOutput.PreContent.SetContent("<cache>");
            tagHelperOutput.PostContent.SetContent("</cache>");
            var cacheTagHelper = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
            };

            var cacheTagKey = new CacheTagKey(cacheTagHelper, tagHelperContext);
            var key         = cacheTagKey.GenerateKey();

            // Act - 1
            await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);

            Task <IHtmlContent> cachedValue;
            var result = cache.TryGetValue(cacheTagKey, out cachedValue);

            // Assert - 1
            Assert.Equal("HtmlEncode[[some-content]]", tagHelperOutput.Content.GetContent());
            Assert.True(result);

            // Act - 2
            tokenSource.Cancel();
            result = cache.TryGetValue(cacheTagKey, out cachedValue);

            // Assert - 2
            Assert.False(result);
            Assert.Null(cachedValue);
        }
コード例 #3
0
        public async Task ProcessAsync_UsesExpiresAfter_ToExpireCacheEntry()
        {
            // Arrange - 1
            var currentTime   = new DateTimeOffset(2010, 1, 1, 0, 0, 0, TimeSpan.Zero);
            var id            = "unique-id";
            var childContent1 = "original-child-content";
            var clock         = new Mock <ISystemClock>();

            clock.SetupGet(p => p.UtcNow)
            .Returns(() => currentTime);
            var cache = new MemoryCache(new MemoryCacheOptions {
                Clock = clock.Object
            });
            var tagHelperContext1 = GetTagHelperContext(id);
            var tagHelperOutput1  = GetTagHelperOutput(childContent: childContent1);

            tagHelperOutput1.PreContent.SetContent("<cache>");
            tagHelperOutput1.PostContent.SetContent("</cache>");
            var cacheTagHelper1 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                ViewContext  = GetViewContext(),
                ExpiresAfter = TimeSpan.FromMinutes(10)
            };

            // Act - 1
            await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);

            // Assert - 1
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.True(tagHelperOutput1.IsContentModified);
            Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());

            // Arrange - 2
            var childContent2     = "different-content";
            var tagHelperContext2 = GetTagHelperContext(id);
            var tagHelperOutput2  = GetTagHelperOutput(childContent: childContent2);

            tagHelperOutput2.PreContent.SetContent("<cache>");
            tagHelperOutput2.PostContent.SetContent("</cache>");
            var cacheTagHelper2 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                ViewContext  = GetViewContext(),
                ExpiresAfter = TimeSpan.FromMinutes(10)
            };

            currentTime = currentTime.AddMinutes(11);

            // Act - 2
            await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);

            // Assert - 2
            Assert.Empty(tagHelperOutput2.PreContent.GetContent());
            Assert.Empty(tagHelperOutput2.PostContent.GetContent());
            Assert.True(tagHelperOutput2.IsContentModified);
            Assert.Equal(childContent2, tagHelperOutput2.Content.GetContent());
        }
コード例 #4
0
        public async Task ProcessAsync_RecalculatesValueIfCacheKeyChanges()
        {
            // Arrange - 1
            var id                = "unique-id";
            var childContent1     = "original-child-content";
            var cache             = new MemoryCache(new MemoryCacheOptions());
            var tagHelperContext1 = GetTagHelperContext(id);
            var tagHelperOutput1  = GetTagHelperOutput(childContent: childContent1);

            tagHelperOutput1.PreContent.Append("<cache>");
            tagHelperOutput1.PostContent.SetContent("</cache>");
            var cacheTagHelper1 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                VaryByCookie = "cookie1,cookie2",
                ViewContext  = GetViewContext(),
            };

            cacheTagHelper1.ViewContext.HttpContext.Request.Headers["Cookie"] = "cookie1=value1;cookie2=value2";

            // Act - 1
            await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);

            // Assert - 1
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.True(tagHelperOutput1.IsContentModified);
            Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());

            // Arrange - 2
            var childContent2     = "different-content";
            var tagHelperContext2 = GetTagHelperContext(id);
            var tagHelperOutput2  = GetTagHelperOutput(childContent: childContent2);

            tagHelperOutput2.PreContent.SetContent("<cache>");
            tagHelperOutput2.PostContent.SetContent("</cache>");
            var cacheTagHelper2 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                VaryByCookie = "cookie1,cookie2",
                ViewContext  = GetViewContext(),
            };

            cacheTagHelper2.ViewContext.HttpContext.Request.Headers["Cookie"] = "cookie1=value1;cookie2=not-value2";

            // Act - 2
            await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);

            // Assert - 2
            Assert.Empty(tagHelperOutput2.PreContent.GetContent());
            Assert.Empty(tagHelperOutput2.PostContent.GetContent());
            Assert.True(tagHelperOutput2.IsContentModified);
            Assert.Equal(childContent2, tagHelperOutput2.Content.GetContent());
        }
コード例 #5
0
        public async Task ProcessAsync_ReturnsCachedValue_IfVaryByParamIsUnchanged()
        {
            // Arrange - 1
            var id                = "unique-id";
            var childContent      = "original-child-content";
            var cache             = new MemoryCache(new MemoryCacheOptions());
            var tagHelperContext1 = GetTagHelperContext(id);
            var tagHelperOutput1  = GetTagHelperOutput(
                attributes: new TagHelperAttributeList(),
                childContent: childContent);
            var cacheTagHelper1 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                VaryByQuery = "key1,key2",
                ViewContext = GetViewContext(),
            };

            cacheTagHelper1.ViewContext.HttpContext.Request.QueryString = new QueryString(
                "?key1=value1&key2=value2");

            // Act - 1
            await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);

            // Assert - 1
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.True(tagHelperOutput1.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput1.Content.GetContent());

            // Arrange - 2
            var tagHelperContext2 = GetTagHelperContext(id);
            var tagHelperOutput2  = GetTagHelperOutput(
                attributes: new TagHelperAttributeList(),
                childContent: "different-content");
            var cacheTagHelper2 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                VaryByQuery = "key1,key2",
                ViewContext = GetViewContext(),
            };

            cacheTagHelper2.ViewContext.HttpContext.Request.QueryString = new QueryString(
                "?key1=value1&key2=value2");

            // Act - 2
            await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);

            // Assert - 2
            Assert.Empty(tagHelperOutput2.PreContent.GetContent());
            Assert.Empty(tagHelperOutput2.PostContent.GetContent());
            Assert.True(tagHelperOutput2.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput2.Content.GetContent());
        }
コード例 #6
0
        public async Task ProcessAsync_SetsEntrySize_ForPlaceholderAndFinalCacheEntries()
        {
            // Arrange
            var mockCache = new Mock <IMemoryCache>();
            var tempEntry = new Mock <ICacheEntry>();

            tempEntry.SetupAllProperties();
            tempEntry.Setup(e => e.ExpirationTokens).Returns(new List <IChangeToken>());
            tempEntry.Setup(e => e.PostEvictionCallbacks).Returns(new List <PostEvictionCallbackRegistration>());
            var finalEntry = new Mock <ICacheEntry>();

            finalEntry.SetupAllProperties();
            finalEntry.Setup(e => e.ExpirationTokens).Returns(new List <IChangeToken>());
            finalEntry.Setup(e => e.PostEvictionCallbacks).Returns(new List <PostEvictionCallbackRegistration>());
            object value;

            mockCache
            .Setup(s => s.TryGetValue(It.IsAny <object>(), out value))
            .Returns(false);

            mockCache.SetupSequence(mc => mc.CreateEntry(It.IsAny <object>()))
            .Returns(tempEntry.Object)
            .Returns(finalEntry.Object);

            var id                = "unique-id";
            var childContent1     = "original-child-content";
            var tagHelperContext1 = GetTagHelperContext(id);
            var tagHelperOutput1  = GetTagHelperOutput(childContent: childContent1);

            tagHelperOutput1.PreContent.Append("<cache>");
            tagHelperOutput1.PostContent.SetContent("</cache>");
            var cacheTagHelper1 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(mockCache.Object), new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
            };

            // Act
            await cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1);

            // Assert
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.True(tagHelperOutput1.IsContentModified);
            Assert.Equal(childContent1, tagHelperOutput1.Content.GetContent());
            tempEntry.VerifySet(e => e.Size  = 64);
            finalEntry.VerifySet(e => e.Size = childContent1.Length * 2);
        }
コード例 #7
0
        public async Task ProcessAsync_WorksForNestedCacheTagHelpers()
        {
            // Arrange
            var expected        = "Hello world";
            var cache           = new MemoryCache(new MemoryCacheOptions());
            var encoder         = new HtmlTestEncoder();
            var cacheTagHelper1 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), encoder)
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var cacheTagHelper2 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), encoder)
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var tagHelperOutput2 = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, _) =>
            {
                var content = new DefaultTagHelperContent();
                content.SetContent(expected);
                return(Task.FromResult <TagHelperContent>(content));
            });

            var tagHelperOutput1 = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: async(useCachedResult, _) =>
            {
                var context = GetTagHelperContext("test2");
                var output  = tagHelperOutput2;
                await cacheTagHelper2.ProcessAsync(context, output);
                return(await output.GetChildContentAsync());
            });

            // Act
            await cacheTagHelper1.ProcessAsync(GetTagHelperContext(), tagHelperOutput1);

            // Assert
            Assert.Equal(encoder.Encode(expected), tagHelperOutput1.Content.GetContent());
        }
コード例 #8
0
        public async Task ProcessAsync_ReturnsCachedValue_IfEnabled()
        {
            // Arrange
            var id           = "unique-id";
            var childContent = "original-child-content";
            var cache        = new Mock <IMemoryCache>();
            var value        = new DefaultTagHelperContent().SetContent("ok");

            cache.Setup(c => c.CreateLinkingScope()).Returns(new Mock <IEntryLink>().Object);
            cache.Setup(c => c.Set(
                            /*key*/ It.IsAny <string>(),
                            /*value*/ It.IsAny <object>(),
                            /*options*/ It.IsAny <MemoryCacheEntryOptions>()))
            .Returns(value);
            object cacheResult;

            cache.Setup(c => c.TryGetValue(It.IsAny <string>(), out cacheResult))
            .Returns(false);
            var tagHelperContext = GetTagHelperContext(id);
            var tagHelperOutput  = GetTagHelperOutput(
                attributes: new TagHelperAttributeList(),
                childContent: childContent);
            var cacheTagHelper = new CacheTagHelper(cache.Object, new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            // Act
            await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);

            // Assert
            Assert.Empty(tagHelperOutput.PreContent.GetContent());
            Assert.Empty(tagHelperOutput.PostContent.GetContent());
            Assert.True(tagHelperOutput.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput.Content.GetContent());

            // There are two calls to set (for the TCS and the processed value)
            cache.Verify(c => c.Set(
                             /*key*/ It.IsAny <string>(),
                             /*value*/ It.IsAny <object>(),
                             /*options*/ It.IsAny <MemoryCacheEntryOptions>()),
                         Times.Exactly(2));
        }
コード例 #9
0
        public async Task ProcessAsync_AwaitersUseTheResultOfExecutor()
        {
            // Arrange
            var expected = "Hello world";
            var cache    = new TestMemoryCache();
            var encoder  = new HtmlTestEncoder();
            // The two instances represent two instances of the same cache tag helper appearance in the page.
            var cacheTagHelper1 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), encoder)
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var cacheTagHelper2 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), encoder)
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var invokeCount = 0;

            Func <bool, HtmlEncoder, Task <TagHelperContent> > getChildContentAsync = (useCachedResult, _) =>
            {
                invokeCount++;

                var content = new DefaultTagHelperContent();
                content.SetContent(expected);
                return(Task.FromResult <TagHelperContent>(content));
            };

            var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList(), getChildContentAsync);
            var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList(), getChildContentAsync);

            // Act
            var task1 = Task.Run(() => cacheTagHelper1.ProcessAsync(GetTagHelperContext(cache.Key1), tagHelperOutput1));
            var task2 = Task.Run(() => cacheTagHelper2.ProcessAsync(GetTagHelperContext(cache.Key2), tagHelperOutput2));

            // Assert
            await Task.WhenAll(task1, task2);

            Assert.Equal(1, invokeCount); // We expect getChildContentAsync to be invoked exactly once.
            Assert.Equal(encoder.Encode(expected), tagHelperOutput1.Content.GetContent());
            Assert.Equal(encoder.Encode(expected), tagHelperOutput2.Content.GetContent());
        }
コード例 #10
0
        public async Task ProcessAsync_DoesNotCache_IfDisabled()
        {
            // Arrange
            var id           = "unique-id";
            var childContent = "original-child-content";
            var cache        = new Mock <IMemoryCache>();
            var value        = new DefaultTagHelperContent().SetContent("ok");

            cache.Setup(c => c.Set(
                            /*key*/ It.IsAny <string>(),
                            /*value*/ value,
                            /*optons*/ It.IsAny <MemoryCacheEntryOptions>()))
            .Returns(value);
            object cacheResult;

            cache.Setup(c => c.TryGetValue(It.IsAny <string>(), out cacheResult))
            .Returns(false);
            var tagHelperContext = GetTagHelperContext(id);
            var tagHelperOutput  = GetTagHelperOutput(
                attributes: new TagHelperAttributeList(),
                childContent: childContent);
            var cacheTagHelper = new CacheTagHelper(cache.Object, new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = false
            };

            // Act
            await cacheTagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);

            // Assert
            Assert.Equal(childContent, tagHelperOutput.Content.GetContent());
            cache.Verify(c => c.Set(
                             /*key*/ It.IsAny <string>(),
                             /*value*/ It.IsAny <object>(),
                             /*options*/ It.IsAny <MemoryCacheEntryOptions>()),
                         Times.Never);
        }
コード例 #11
0
        public async Task ProcessAsync_ThrowsExceptionForAwaiters_IfExecutorEncountersAnException()
        {
            // Arrange
            var expected = new DivideByZeroException();
            var cache    = new TestMemoryCache();
            // The two instances represent two instances of the same cache tag helper appearance in the page.
            var cacheTagHelper1 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };
            var cacheTagHelper2 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var invokeCount     = 0;
            var tagHelperOutput = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, _) =>
            {
                invokeCount++;
                throw expected;
            });

            // Act
            var task1 = Task.Run(() => cacheTagHelper1.ProcessAsync(GetTagHelperContext(cache.Key1), tagHelperOutput));
            var task2 = Task.Run(() => cacheTagHelper2.ProcessAsync(GetTagHelperContext(cache.Key2), tagHelperOutput));

            // Assert
            await Assert.ThrowsAsync <DivideByZeroException>(() => task1);

            await Assert.ThrowsAsync <DivideByZeroException>(() => task2);

            Assert.Equal(1, invokeCount);
        }
コード例 #12
0
        public async Task ProcessAsync_ExceptionInProcessing_DoesntBlockConcurrentRequests()
        {
            // Arrange
            var id           = "unique-id";
            var childContent = "some-content";
            var resetEvent1  = new ManualResetEvent(false);
            var resetEvent2  = new ManualResetEvent(false);
            var calls        = 0;
            var cache        = new MemoryCache(new MemoryCacheOptions());

            var tagHelperContext1 = GetTagHelperContext(id + 1);
            var tagHelperContext2 = GetTagHelperContext(id + 2);

            var tagHelperOutput1 = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                calls++;
                resetEvent2.Set();

                throw new Exception();
            });

            var tagHelperOutput2 = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                calls++;

                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetHtmlContent(childContent);
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });

            var cacheTagHelper1 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var cacheTagHelper2 = new CacheTagHelper(cache, new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            // Act

            var task1 = Task.Run(async() =>
            {
                resetEvent1.WaitOne(5000);
                await Assert.ThrowsAsync <Exception>(() => cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1));
            });

            var task2 = Task.Run(async() =>
            {
                resetEvent2.WaitOne(5000);
                await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
            });

            resetEvent1.Set();
            await Task.WhenAll(task1, task2);

            // Assert
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.False(tagHelperOutput1.IsContentModified);
            Assert.Empty(tagHelperOutput1.Content.GetContent());

            Assert.Empty(tagHelperOutput2.PreContent.GetContent());
            Assert.Empty(tagHelperOutput2.PostContent.GetContent());
            Assert.True(tagHelperOutput2.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput2.Content.GetContent());

            Assert.Equal(2, calls);
        }
コード例 #13
0
        public async Task ProcessAsync_ExceptionInProcessing_DoNotThrowInSubsequentRequests()
        {
            // Arrange
            var id           = "unique-id";
            var childContent = "some-content";
            var cache        = new MemoryCache(new MemoryCacheOptions());

            var counter = 0;

            Task <TagHelperContent> GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
            {
                counter++;
                if (counter < 3)
                {
                    // throw on first two calls
                    throw new Exception();
                }
                else
                {
                    // produce content on third call
                    var tagHelperContent = new DefaultTagHelperContent();
                    tagHelperContent.SetHtmlContent(childContent);
                    return(Task.FromResult <TagHelperContent>(tagHelperContent));
                }
            }

            var tagHelperContext1 = GetTagHelperContext(id);
            var tagHelperContext2 = GetTagHelperContext(id);
            var tagHelperContext3 = GetTagHelperContext(id);
            var tagHelperContext4 = GetTagHelperContext(id);

            var tagHelperOutput1 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync);
            var tagHelperOutput2 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync);
            var tagHelperOutput3 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync);
            var tagHelperOutput4 = new TagHelperOutput("cache", new TagHelperAttributeList(), GetChildContentAsync);

            var cacheTagHelper = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
            {
                ViewContext  = GetViewContext(),
                Enabled      = true,
                ExpiresAfter = TimeSpan.FromHours(1.0)
            };

            // Act - 1

            await Assert.ThrowsAsync <Exception>(() => cacheTagHelper.ProcessAsync(tagHelperContext1, tagHelperOutput1));

            // Assert - 1

            Assert.Equal(1, counter);
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.False(tagHelperOutput1.IsContentModified);
            Assert.Empty(tagHelperOutput1.Content.GetContent());

            // Act - 2

            await Assert.ThrowsAsync <Exception>(() => cacheTagHelper.ProcessAsync(tagHelperContext2, tagHelperOutput2));

            // Assert - 2

            Assert.Equal(2, counter);
            Assert.Empty(tagHelperOutput2.PreContent.GetContent());
            Assert.Empty(tagHelperOutput2.PostContent.GetContent());
            Assert.False(tagHelperOutput2.IsContentModified);
            Assert.Empty(tagHelperOutput2.Content.GetContent());

            // Act - 3

            await cacheTagHelper.ProcessAsync(tagHelperContext3, tagHelperOutput3);

            // Assert - 3

            Assert.Equal(3, counter);
            Assert.Empty(tagHelperOutput3.PreContent.GetContent());
            Assert.Empty(tagHelperOutput3.PostContent.GetContent());
            Assert.True(tagHelperOutput3.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput3.Content.GetContent());

            // Act - 4

            await cacheTagHelper.ProcessAsync(tagHelperContext4, tagHelperOutput4);

            // Assert - 4

            Assert.Equal(3, counter);
            Assert.Empty(tagHelperOutput4.PreContent.GetContent());
            Assert.Empty(tagHelperOutput4.PostContent.GetContent());
            Assert.True(tagHelperOutput4.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput4.Content.GetContent());
        }
コード例 #14
0
        public async Task ProcessAsync_ExceptionInProcessing_DoesntBlockConcurrentRequests()
        {
            // Arrange
            var id           = "unique-id";
            var childContent = "some-content";
            var event1       = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
            var event2       = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
            var event3       = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
            var calls        = 0;
            var cache        = new MemoryCache(new MemoryCacheOptions());

            var tagHelperContext1 = GetTagHelperContext(id + 1);
            var tagHelperContext2 = GetTagHelperContext(id + 2);

            var tagHelperOutput1 = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                calls++;
                event2.SetResult(0);

                throw new Exception();
            });

            var tagHelperOutput2 = new TagHelperOutput(
                "cache",
                new TagHelperAttributeList(),
                getChildContentAsync: async(useCachedResult, encoder) =>
            {
                calls++;
                await event3.Task.TimeoutAfter(TimeSpan.FromSeconds(5));

                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetHtmlContent(childContent);
                return(tagHelperContent);
            });

            var cacheTagHelper1 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            var cacheTagHelper2 = new CacheTagHelper(new CacheTagHelperMemoryCacheFactory(cache), new HtmlTestEncoder())
            {
                ViewContext = GetViewContext(),
                Enabled     = true
            };

            // Act

            var task1 = Task.Run(async() =>
            {
                await event1.Task.TimeoutAfter(TimeSpan.FromSeconds(5));
                await Assert.ThrowsAsync <Exception>(() => cacheTagHelper1.ProcessAsync(tagHelperContext1, tagHelperOutput1));
                event3.SetResult(0);
            });

            var task2 = Task.Run(async() =>
            {
                await event2.Task.TimeoutAfter(TimeSpan.FromSeconds(5));
                await cacheTagHelper2.ProcessAsync(tagHelperContext2, tagHelperOutput2);
            });

            event1.SetResult(0);
            await Task.WhenAll(task1, task2);

            // Assert
            Assert.Empty(tagHelperOutput1.PreContent.GetContent());
            Assert.Empty(tagHelperOutput1.PostContent.GetContent());
            Assert.False(tagHelperOutput1.IsContentModified);
            Assert.Empty(tagHelperOutput1.Content.GetContent());

            Assert.Empty(tagHelperOutput2.PreContent.GetContent());
            Assert.Empty(tagHelperOutput2.PostContent.GetContent());
            Assert.True(tagHelperOutput2.IsContentModified);
            Assert.Equal(childContent, tagHelperOutput2.Content.GetContent());

            Assert.Equal(2, calls);
        }