/// <summary>
        /// Initializes a new instance of <see cref="CompilerCacheResult"/> with the specified
        /// <see cref="Compilation.CompilationResult"/>.
        /// </summary>
        /// <param name="compilationResult">The <see cref="Compilation.CompilationResult"/>.</param>
        /// <param name="expirationTokens">One or more <see cref="IChangeToken"/> instances that indicate when
        /// this result has expired.</param>
        public CompilerCacheResult(CompilationResult compilationResult, IList<IChangeToken> expirationTokens)
        {
            if (expirationTokens == null)
            {
                throw new ArgumentNullException(nameof(expirationTokens));
            }

            CompilationResult = compilationResult;
            Success = true;
            ExpirationTokens = expirationTokens;
        }
Beispiel #2
0
        public void GetOrAdd_ReturnsCompilationResultFromFactory()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            fileProvider.AddFile(ViewPath, "some content");
            var cache = new CompilerCache(fileProvider);
            var expected = new CompilationResult(typeof(TestView));

            // Act
            var result = cache.GetOrAdd(ViewPath, _ => expected);

            // Assert
            Assert.True(result.Success);
            Assert.IsType<TestView>(result.PageFactory());
            Assert.Same(ViewPath, result.PageFactory().Path);
        }
Beispiel #3
0
        public void EnsureSuccessful_ThrowsIfCompilationFailed()
        {
            // Arrange
            var compilationFailure = new CompilationFailure(
                "test",
                sourceFileContent: string.Empty,
                compiledContent: string.Empty,
                messages: Enumerable.Empty<AspNetCore.Diagnostics.DiagnosticMessage>());
            var failures = new[] { compilationFailure };
            var result = new CompilationResult(failures);

            // Act and Assert
            Assert.Null(result.CompiledType);
            Assert.Same(failures, result.CompilationFailures);
            var exception = Assert.Throws<CompilationFailedException>(() => result.EnsureSuccessful());
            var failure = Assert.Single(exception.CompilationFailures);
            Assert.Same(compilationFailure, failure);
        }
Beispiel #4
0
        /// <summary>
        /// Initializes a new instance of <see cref="CompilerCacheResult"/> with the specified
        /// <see cref="Compilation.CompilationResult"/>.
        /// </summary>
        /// <param name="relativePath">Path of the view file relative to the application base.</param>
        /// <param name="compilationResult">The <see cref="Compilation.CompilationResult"/>.</param>
        /// <param name="expirationTokens">One or more <see cref="IChangeToken"/> instances that indicate when
        /// this result has expired.</param>
        public CompilerCacheResult(string relativePath, CompilationResult compilationResult, IList<IChangeToken> expirationTokens)
        {
            if (expirationTokens == null)
            {
                throw new ArgumentNullException(nameof(expirationTokens));
            }

            ExpirationTokens = expirationTokens;
            var compiledType = compilationResult.CompiledType;

            var newExpression = Expression.New(compiledType);

            var pathProperty = compiledType.GetProperty(nameof(IRazorPage.Path));

            var propertyBindExpression = Expression.Bind(pathProperty, Expression.Constant(relativePath));
            var objectInitializeExpression = Expression.MemberInit(newExpression, propertyBindExpression);
            PageFactory =  Expression
                .Lambda<Func<IRazorPage>>(objectInitializeExpression)
                .Compile();
        }
Beispiel #5
0
        public void GetOrAdd_NormalizesPathSepartorForPaths(string relativePath)
        {
            // Arrange
            var viewPath = "/Areas/Finances/Views/Home/Index.cshtml";
            var fileProvider = new TestFileProvider();
            fileProvider.AddFile(viewPath, "some content");
            var cache = new CompilerCache(fileProvider);
            var expected = new CompilationResult(typeof(TestView));

            // Act - 1
            var result1 = cache.GetOrAdd(@"Areas\Finances\Views\Home\Index.cshtml", _ => expected);

            // Assert - 1
            Assert.IsType<TestView>(result1.PageFactory());

            // Act - 2
            var result2 = cache.GetOrAdd(relativePath, ThrowsIfCalled);

            // Assert - 2
            Assert.IsType<TestView>(result2.PageFactory());
            Assert.Same(result1.PageFactory, result2.PageFactory);
        }
 /// <summary>
 /// Initializes a new instance of <see cref="CompilerCacheResult"/> with the specified
 /// <see cref="Compilation.CompilationResult"/>.
 /// </summary>
 /// <param name="compilationResult">The <see cref="Compilation.CompilationResult"/>.</param>
 public CompilerCacheResult(CompilationResult compilationResult)
     : this(compilationResult, new IChangeToken[0])
 {
 }
Beispiel #7
0
        public void GetOrAdd_ReturnsFailedCompilationResult_IfFileWasRemovedFromFileSystem()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            fileProvider.AddFile(ViewPath, "some content");
            var cache = new CompilerCache(fileProvider);
            var expected = new CompilationResult(typeof(TestView));

            // Act 1
            var result1 = cache.GetOrAdd(ViewPath, _ => expected);

            // Assert 1
            Assert.True(result1.Success);
            Assert.IsType<TestView>(result1.PageFactory());

            // Act 2
            // Delete the file from the file system and set it's expiration token.
            fileProvider.DeleteFile(ViewPath);
            fileProvider.GetChangeToken(ViewPath).HasChanged = true;
            var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled);

            // Assert 2
            Assert.False(result2.Success);
        }
Beispiel #8
0
        public void GetOrAdd_CachesExceptionsInCompilationResult()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            fileProvider.AddFile(ViewPath, "some content");
            var cache = new CompilerCache(fileProvider);
            var diagnosticMessages = new[]
            {
                new AspNetCore.Diagnostics.DiagnosticMessage("message", "message", ViewPath, 1, 1, 1, 1)
            };
            var compilationResult = new CompilationResult(new[]
            {
                new CompilationFailure(ViewPath, "some content", "compiled content", diagnosticMessages)
            });

            // Act and Assert - 1
            var ex = Assert.Throws<CompilationFailedException>(() => cache.GetOrAdd(ViewPath, _ => compilationResult));
            Assert.Same(compilationResult.CompilationFailures, ex.CompilationFailures);

            // Act and Assert - 2
            ex = Assert.Throws<CompilationFailedException>(() => cache.GetOrAdd(ViewPath, ThrowsIfCalled));
            Assert.Same(compilationResult.CompilationFailures, ex.CompilationFailures);
        }
Beispiel #9
0
        public void GetOrAdd_ReturnsRuntimeCompiledAndPrecompiledViews()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            fileProvider.AddFile(ViewPath, "some content");
            var cache = new CompilerCache(fileProvider, _precompiledViews);
            var expected = new CompilationResult(typeof(TestView));

            // Act 1
            var result1 = cache.GetOrAdd(ViewPath, _ => expected);

            // Assert 1
            Assert.IsType<TestView>(result1.PageFactory());

            // Act 2
            var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled);

            // Assert 2
            Assert.True(result2.Success);
            Assert.IsType<TestView>(result2.PageFactory());

            // Act 3
            var result3 = cache.GetOrAdd(PrecompiledViewsPath, ThrowsIfCalled);

            // Assert 3
            Assert.True(result2.Success);
            Assert.IsType<PreCompile>(result3.PageFactory());
        }
Beispiel #10
0
        public void GetOrAdd_DoesNotQueryFileSystem_IfCachedFileTriggerWasNotSet()
        {
            // Arrange
            var mockFileProvider = new Mock<TestFileProvider> { CallBase = true };
            var fileProvider = mockFileProvider.Object;
            fileProvider.AddFile(ViewPath, "some content");
            var cache = new CompilerCache(fileProvider);
            var expected = new CompilationResult(typeof(TestView));

            // Act 1
            var result1 = cache.GetOrAdd(ViewPath, _ => expected);

            // Assert 1
            Assert.True(result1.Success);
            Assert.IsType<TestView>(result1.PageFactory());

            // Act 2
            var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled);

            // Assert 2
            Assert.True(result2.Success);
            Assert.IsType<TestView>(result2.PageFactory());
            mockFileProvider.Verify(v => v.GetFileInfo(ViewPath), Times.Once());
        }
Beispiel #11
0
        public void GetOrAdd_ReturnsNewResult_IfAncestorViewImportsWereModified(string globalImportPath)
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            fileProvider.AddFile(ViewPath, "some content");
            var cache = new CompilerCache(fileProvider);
            var expected1 = new CompilationResult(typeof(TestView));
            var expected2 = new CompilationResult(typeof(DifferentView));

            // Act 1
            var result1 = cache.GetOrAdd(ViewPath, _ => expected1);

            // Assert 1
            Assert.True(result1.Success);
            Assert.IsType<TestView>(result1.PageFactory());

            // Act 2
            // Verify we're getting cached results.
            var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled);

            // Assert 2
            Assert.True(result2.Success);
            Assert.IsType<TestView>(result2.PageFactory());

            // Act 3
            fileProvider.GetChangeToken(globalImportPath).HasChanged = true;
            var result3 = cache.GetOrAdd(ViewPath, _ => expected2);

            // Assert 2
            Assert.True(result3.Success);
            Assert.IsType<DifferentView>(result3.PageFactory());
        }
        public void Compile_ReturnsResultFromCompilationServiceIfParseSucceeds()
        {
            // Arrange
            var code = "compiled-content";
            var generatorResult = new GeneratorResults(
                    new Block(new BlockBuilder { Type = BlockType.Comment }),
                    Enumerable.Empty<TagHelperDescriptor>(),
                    new ErrorSink(),
                    new CodeGeneratorResult(code, new LineMapping[0]),
                    new ChunkTree());
            var host = new Mock<IMvcRazorHost>();
            host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
                .Returns(generatorResult);

            var fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.CreateReadStream())
                    .Returns(Stream.Null);
            var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");

            var compilationResult = new CompilationResult(typeof(object));
            var compiler = new Mock<ICompilationService>();
            compiler.Setup(c => c.Compile(relativeFileInfo, code))
                    .Returns(compilationResult)
                    .Verifiable();
            var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);

            // Act
            var result = razorService.Compile(relativeFileInfo);

            // Assert
            Assert.Same(compilationResult.CompiledType, result.CompiledType);
            compiler.Verify();
        }
Beispiel #13
0
 /// <summary>
 /// Initializes a new instance of <see cref="CompilerCacheResult"/> with the specified
 /// <see cref="Compilation.CompilationResult"/>.
 /// </summary>
 /// <param name="relativePath">Path of the view file relative to the application base.</param>
 /// <param name="compilationResult">The <see cref="Compilation.CompilationResult"/>.</param>
 public CompilerCacheResult(string relativePath, CompilationResult compilationResult)
     : this(relativePath, compilationResult, new IChangeToken[0])
 {
 }