/// <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; }
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); }
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); }
/// <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(); }
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]) { }
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); }
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); }
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()); }
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()); }
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(); }
/// <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]) { }