public void GetInheritedChunks_ReadsChunksFromGlobalFilesInPath() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(@"Views\accounts\_GlobalImport.cshtml", "@using AccountModels"); fileProvider.AddFile(@"Views\Shared\_GlobalImport.cshtml", "@inject SharedHelper Shared"); fileProvider.AddFile(@"Views\home\_GlobalImport.cshtml", "@using MyNamespace"); fileProvider.AddFile(@"Views\_GlobalImport.cshtml", @"@inject MyHelper<TModel> Helper @inherits MyBaseType @{ Layout = ""test.cshtml""; } "); var defaultChunks = new Chunk[] { new InjectChunk("MyTestHtmlHelper", "Html"), new UsingChunk { Namespace = "AppNamespace.Model" }, }; var cache = new DefaultCodeTreeCache(fileProvider); var host = new MvcRazorHost(cache); var utility = new ChunkInheritanceUtility(host, cache, defaultChunks); // Act var codeTrees = utility.GetInheritedCodeTrees(@"Views\home\Index.cshtml"); // Assert Assert.Equal(2, codeTrees.Count); var viewStartChunks = codeTrees[0].Chunks; Assert.Equal(3, viewStartChunks.Count); Assert.IsType<LiteralChunk>(viewStartChunks[0]); var usingChunk = Assert.IsType<UsingChunk>(viewStartChunks[1]); Assert.Equal("MyNamespace", usingChunk.Namespace); Assert.IsType<LiteralChunk>(viewStartChunks[2]); viewStartChunks = codeTrees[1].Chunks; Assert.Equal(5, viewStartChunks.Count); Assert.IsType<LiteralChunk>(viewStartChunks[0]); var injectChunk = Assert.IsType<InjectChunk>(viewStartChunks[1]); Assert.Equal("MyHelper<TModel>", injectChunk.TypeName); Assert.Equal("Helper", injectChunk.MemberName); var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(viewStartChunks[2]); Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName); Assert.IsType<StatementChunk>(viewStartChunks[3]); Assert.IsType<LiteralChunk>(viewStartChunks[4]); }
public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas() { // Arrange var viewPath = "some-relative-path"; var fileContent = "test file content"; var content = $@" #line 1 ""{viewPath}"" this should fail"; var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(viewPath, fileContent); var compilationService = new DefaultRoslynCompilationService( GetDependencyContext(), GetOptions(), GetFileProviderAccessor(fileProvider), NullLoggerFactory.Instance); var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path"); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType<CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath); Assert.Equal(fileContent, compilationFailure.SourceFileContent); }
public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas() { // Arrange var viewPath = "some-relative-path"; var fileContent = "test file content"; var content = $@" #line 1 ""{viewPath}"" this should fail"; var applicationEnvironment = PlatformServices.Default.Application; var libraryExporter = CompilationServices.Default.LibraryExporter; var mvcRazorHost = Mock.Of<IMvcRazorHost>(); var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(viewPath, fileContent); var compilationService = new RoslynCompilationService( applicationEnvironment, libraryExporter, mvcRazorHost, GetOptions(), GetFileProviderAccessor(fileProvider), NullLoggerFactory.Instance); var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path"); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType<CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath); Assert.Equal(fileContent, compilationFailure.SourceFileContent); }
public void GetOrAdd_UpdatesCache_IfFileExpirationTriggerExpires() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "test content"); using (var chunkTreeCache = new DefaultChunkTreeCache(fileProvider)) { var expected1 = new ChunkTree(); var expected2 = new ChunkTree(); // Act 1 var result1 = chunkTreeCache.GetOrAdd(path, fileInfo => expected1); // Assert 1 Assert.Same(expected1, result1); // Act 2 fileProvider.GetChangeToken(path).HasChanged = true; var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => expected2); // Assert 2 Assert.Same(expected2, result2); } }
public void GetOrAdd_ReturnsFileNotFoundIfFileWasDeleted() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(Enumerable.Empty<RazorFileInfoCollection>(), TestLoadContext, fileProvider); var type = typeof(TestView); var expected = UncachedCompilationResult.Successful(type, "hello world"); // Act 1 var result1 = cache.GetOrAdd(ViewPath, _ => expected); // Assert 1 Assert.NotSame(CompilerCacheResult.FileNotFound, result1); Assert.Same(expected, result1.CompilationResult); // Act 2 // Delete the file from the file system and set it's expiration trigger. fileProvider.DeleteFile(ViewPath); fileProvider.GetTrigger(ViewPath).IsExpired = true; var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled); // Assert 2 Assert.Same(CompilerCacheResult.FileNotFound, result2); Assert.Null(result2.CompilationResult); }
public void GetInheritedChunks_ReturnsEmptySequenceIfNoGlobalsArePresent() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(@"_GlobalImport.cs", string.Empty); fileProvider.AddFile(@"Views\_Layout.cshtml", string.Empty); fileProvider.AddFile(@"Views\home\_not-globalimport.cshtml", string.Empty); var cache = new DefaultCodeTreeCache(fileProvider); var host = new MvcRazorHost(cache); var defaultChunks = new Chunk[] { new InjectChunk("MyTestHtmlHelper", "Html"), new UsingChunk { Namespace = "AppNamespace.Model" }, }; var utility = new ChunkInheritanceUtility(host, cache, defaultChunks); // Act var codeTrees = utility.GetInheritedCodeTrees(@"Views\home\Index.cshtml"); // Assert Assert.Empty(codeTrees); }
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 GetOrAdd_ReturnsCompilationResultFromFactory() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(fileProvider); var type = typeof(TestView); var expected = UncachedCompilationResult.Successful(type, "hello world"); // Act var result = cache.GetOrAdd(ViewPath, _ => expected); // Assert Assert.NotSame(CompilerCacheResult.FileNotFound, result); var actual = Assert.IsType<UncachedCompilationResult>(result.CompilationResult); Assert.NotNull(actual); Assert.Same(expected, actual); Assert.Equal("hello world", actual.CompiledContent); Assert.Same(type, actual.CompiledType); }
public async Task CompileAsync_AddsChangeTokensForViewStartsIfFileExists() { // Arrange var path = "/file/exists/FilePath.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "Content"); var viewCompiler = GetViewCompiler(fileProvider); // Act var result = await viewCompiler.CompileAsync(path); // Assert Assert.NotNull(result.ViewAttribute); Assert.Collection( result.ExpirationTokens, token => Assert.Same(fileProvider.GetChangeToken(path), token), token => Assert.Same(fileProvider.GetChangeToken("/file/exists/_ViewImports.cshtml"), token), token => Assert.Same(fileProvider.GetChangeToken("/file/_ViewImports.cshtml"), token), token => Assert.Same(fileProvider.GetChangeToken("/_ViewImports.cshtml"), token)); }
public async Task CompileAsync_ReturnsPrecompiledViews() { // Arrange var path = "/Views/Home/Index.cshtml"; var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(path, "some content"); var precompiledView = new CompiledViewDescriptor { RelativePath = path, }; var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView }); // Act var result = await viewCompiler.CompileAsync(path); // Assert Assert.Same(precompiledView, result); // This view doesn't have checksums so it can't be recompiled. Assert.Null(precompiledView.ExpirationTokens); }
private IFileProvider GetFileProvider() { TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/a"); fileProvider.AddDirectory("/b"); fileProvider.AddFile("/a/1.md", @"File a1"); fileProvider.AddFile("/a/1.md.meta", @"data: a1"); fileProvider.AddFile("/a/1.md.other", @"data: other"); fileProvider.AddFile("/a/2.md", @"File a2"); fileProvider.AddFile("/a/2.md.meta", @"data: a2"); fileProvider.AddFile("/b/1.md", @"File b1"); fileProvider.AddFile("/b/1.md.meta", @"data: b1"); return(fileProvider); }
private IFileProvider GetFileProvider() { TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/TestFiles"); fileProvider.AddDirectory("/TestFiles/Input"); fileProvider.AddDirectory("/TestFiles/Input/Subfolder"); fileProvider.AddFile("/TestFiles/test-above-input.txt", "test"); fileProvider.AddFile("/TestFiles/Input/markdown-x.md", "xxx"); fileProvider.AddFile("/TestFiles/Input/test-a.txt", "aaa"); fileProvider.AddFile("/TestFiles/Input/test-b.txt", "bbb"); fileProvider.AddFile("/TestFiles/Input/Subfolder/markdown-y.md", "yyy"); fileProvider.AddFile("/TestFiles/Input/Subfolder/test-c.txt", "ccc"); fileProvider.AddFile("/TestFiles/Input/.dotfile", "dotfile"); return(fileProvider); }
public void Compile_DoesNotThrow_IfFileCannotBeRead() { // Arrange var path = "some-relative-path"; var content = $@" #line 1 ""{path}"" this should fail"; var applicationEnvironment = PlatformServices.Default.Application; var libraryExporter = CompilationServices.Default.LibraryExporter; var mvcRazorHost = Mock.Of <IMvcRazorHost>(); var mockFileInfo = new Mock <IFileInfo>(); mockFileInfo.Setup(f => f.CreateReadStream()) .Throws(new Exception()); var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, mockFileInfo.Object); var compilationService = new RoslynCompilationService( applicationEnvironment, libraryExporter, mvcRazorHost, GetOptions(), GetFileProviderAccessor(fileProvider), NullLoggerFactory.Instance); var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType <CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(path, compilationFailure.SourceFilePath); Assert.Null(compilationFailure.SourceFileContent); }
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); }
public void OnProvidersExecuting_ThrowsIfRouteTemplateHasOverridePattern() { // Arrange var fileProvider = new TestFileProvider(); var file = fileProvider.AddFile("/Index.cshtml", "@page \"/custom-route\""); fileProvider.AddDirectoryContent("/", new[] { file }); var project = new TestRazorProject(fileProvider); var optionsManager = Options.Create(new RazorPagesOptions()); optionsManager.Value.RootDirectory = "/"; var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance); var context = new PageRouteModelProviderContext(); // Act & Assert var ex = Assert.Throws <InvalidOperationException>(() => provider.OnProvidersExecuting(context)); Assert.Equal("The route for the page at '/Index.cshtml' cannot start with / or ~/. Pages do not support overriding the file path of the page.", ex.Message); }
public void GetOrAdd_ReturnsCompilationResultFromFactory() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(Enumerable.Empty <RazorFileInfoCollection>(), TestLoadContext, fileProvider); var type = typeof(TestView); var expected = UncachedCompilationResult.Successful(type, "hello world"); // Act var result = cache.GetOrAdd(ViewPath, _ => expected); // Assert Assert.NotSame(CompilerCacheResult.FileNotFound, result); var actual = Assert.IsType <UncachedCompilationResult>(result.CompilationResult); Assert.NotNull(actual); Assert.Same(expected, actual); Assert.Equal("hello world", actual.CompiledContent); Assert.Same(type, actual.CompiledType); }
public void GetOrAdd_UpdatesCacheWithValue_IfFileWasAdded() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); var chunkTreeCache = new DefaultChunkTreeCache(fileProvider); var expected = new ChunkTree(); // Act 1 var result1 = chunkTreeCache.GetOrAdd(path, fileInfo => { throw new Exception("Shouldn't be called."); }); // Assert 1 Assert.Null(result1); // Act 2 fileProvider.AddFile(path, "test content"); fileProvider.GetTrigger(path).IsExpired = true; var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => expected); // Assert 2 Assert.Same(expected, result2); }
public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas() { // Arrange var viewPath = "some-relative-path"; var fileContent = "test file content"; var content = $@" #line 1 ""{viewPath}"" this should fail"; var applicationEnvironment = GetApplicationEnvironment(); var accessor = GetLoadContextAccessor(); var libraryExporter = GetLibraryExporter(); var compilerOptionsProvider = new Mock<ICompilerOptionsProvider>(); compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationName, applicationEnvironment.RuntimeFramework, applicationEnvironment.Configuration)) .Returns(new CompilerOptions()); var mvcRazorHost = Mock.Of<IMvcRazorHost>(); var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(viewPath, fileContent); var compilationService = new RoslynCompilationService(applicationEnvironment, accessor, libraryExporter, compilerOptionsProvider.Object, mvcRazorHost, GetOptions(fileProvider)); var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path"); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType<CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath); Assert.Equal(fileContent, compilationFailure.SourceFileContent); }
public void ShouldReturnExistingFiles(string directory, string[] patterns, string[] expected) { TestContext.Out.WriteLine($"Patterns: {string.Join(",", patterns)}"); // Given FileSystem fileSystem = new FileSystem(); fileSystem.FileProviders.Add(string.Empty, GetFileProvider()); TestFileProvider alternateProvider = new TestFileProvider(); alternateProvider.AddDirectory("/"); alternateProvider.AddDirectory("/q"); alternateProvider.AddFile("/q/werty.txt"); fileSystem.FileProviders.Add("qwerty", alternateProvider); IDirectory dir = fileSystem.GetDirectory(directory); // When IEnumerable <IFile> results = fileSystem.GetFiles(dir, patterns); // Then CollectionAssert.AreEquivalent(expected, results.Select(x => x.Path.FullPath)); }
public async Task CompileAsync_PrecompiledViewWithChecksum_CanRecompile() { // Arrange var path = "/Views/Home/Index.cshtml"; var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(path, "some content"); var expected2 = new CompiledViewDescriptor(); var precompiledView = new CompiledViewDescriptor { RelativePath = path, Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[] { new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path), }), }; var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView }); viewCompiler.AllowRecompilingViewsOnFileChange = true; // Act - 1 var result = await viewCompiler.CompileAsync(path); // Assert - 1 Assert.Same(precompiledView.Item, result.Item); Assert.NotEmpty(result.ExpirationTokens); // Act - 2 fileInfo.Content = "some other content"; fileProvider.GetChangeToken(path).HasChanged = true; viewCompiler.Compile = _ => expected2; result = await viewCompiler.CompileAsync(path); // Assert - 2 Assert.Same(expected2, result); }
public void LookupFileInfo_ReturnsTrue_IfFileExists() { // Arrange var options = new StaticFileOptions(); var fileProvider = new TestFileProvider(); fileProvider.AddFile("/foo.txt", new TestFileInfo { LastModified = new DateTimeOffset(2014, 1, 2, 3, 4, 5, TimeSpan.Zero) }); options.FileProvider = fileProvider; var pathString = new PathString("/test"); var httpContext = new DefaultHttpContext(); httpContext.Request.Path = new PathString("/test/foo.txt"); var context = new StaticFileContext(httpContext, options, pathString, NullLogger.Instance); // Act context.ValidatePath(); var result = context.LookupFileInfo(); // Assert Assert.True(result); }
public void GetOrAdd_ExpiresEntriesAfterOneMinute() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "some content"); var clock = new Mock <ISystemClock>(); var utcNow = DateTimeOffset.UtcNow; clock.SetupGet(c => c.UtcNow) .Returns(() => utcNow); var options = new MemoryCacheOptions { Clock = clock.Object }; var chunkTreeCache = new DefaultChunkTreeCache(fileProvider, options); var chunkTree1 = new ChunkTree(); var chunkTree2 = new ChunkTree(); // Act 1 var result1 = chunkTreeCache.GetOrAdd(path, fileInfo => chunkTree1); // Assert 1 Assert.Same(chunkTree1, result1); // Act 2 utcNow = utcNow.AddSeconds(59); var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => { throw new Exception("Shouldn't be called."); }); // Assert 2 Assert.Same(chunkTree1, result2); // Act 3 utcNow = utcNow.AddSeconds(65); var result3 = chunkTreeCache.GetOrAdd(path, fileInfo => chunkTree2); // Assert 3 Assert.Same(chunkTree2, result3); }
public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas() { // Arrange var viewPath = "some-relative-path"; var fileContent = "test file content"; var content = $@" #line 1 ""{viewPath}"" this should fail"; var applicationEnvironment = GetApplicationEnvironment(); var libraryExporter = GetLibraryExporter(); var compilerOptionsProvider = new Mock <ICompilerOptionsProvider>(); compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationName, applicationEnvironment.RuntimeFramework, applicationEnvironment.Configuration)) .Returns(new CompilerOptions()); var mvcRazorHost = Mock.Of <IMvcRazorHost>(); var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(viewPath, fileContent); var compilationService = new RoslynCompilationService(applicationEnvironment, libraryExporter, compilerOptionsProvider.Object, mvcRazorHost, GetOptions(fileProvider)); var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path"); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType <CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath); Assert.Equal(fileContent, compilationFailure.SourceFileContent); }
private IFileProvider GetFileProvider() { TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/AlternateIgnorePrefix"); fileProvider.AddDirectory("/AlternateViewStart"); fileProvider.AddDirectory("/AlternateViewStartPath"); fileProvider.AddDirectory("/IgnoreUnderscores"); fileProvider.AddDirectory("/Layout"); fileProvider.AddDirectory("/LayoutWithSection"); fileProvider.AddDirectory("/SimpleTemplate"); fileProvider.AddDirectory("/ViewStartAndLayout"); fileProvider.AddFile("/Layout/_Layout.cshtml", @"LAYOUT @RenderBody()"); fileProvider.AddFile("/ViewStartAndLayout/_ViewStart.cshtml", @"@{ Layout = ""_Layout.cshtml""; }"); fileProvider.AddFile("/ViewStartAndLayout/_Layout.cshtml", @"LAYOUT2 @RenderBody()"); fileProvider.AddFile("/AlternateViewStart/_ViewStart.cshtml", @"@{ Layout = @""AlternateViewStart\_Layout.cshtml""; }"); fileProvider.AddFile("/AlternateViewStart/_Layout.cshtml", @"LAYOUT3 @RenderBody()"); fileProvider.AddFile("/IgnoreUnderscores/_Layout.cshtml", @"LAYOUT4 @RenderBody()"); fileProvider.AddFile("/LayoutWithSection/_Layout.cshtml", @"LAYOUT5 @RenderSection(""MySection"", false) @RenderBody()"); return(fileProvider); }
public void ConvertingBadSassFails() { // Given const string input = @" $font-stack: Helvetica, sans-serif $primary-color: #333 body { font: 100% $font-stack; color: $primary-color; }"; TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/input"); fileProvider.AddDirectory("/input/assets"); fileProvider.AddFile("/input/assets/test.scss", input); TestFileSystem fileSystem = new TestFileSystem { FileProvider = fileProvider }; IExecutionContext context = new TestExecutionContext { FileSystem = fileSystem }; IDocument document = new TestDocument(input, new MetadataItems { { Keys.RelativeFilePath, new FilePath("assets/test.scss") } }); Sass sass = new Sass(); // When, Then Assert.Catch <AggregateException>(() => { sass.Execute(new[] { document }, context).ToList(); // Make sure to materialize the result list }); }
public void IncludesFile() { // Given TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/A"); fileProvider.AddDirectory("/A/B"); fileProvider.AddFile("/A/B/c.txt", "foo"); TestFileSystem fileSystem = new TestFileSystem { FileProvider = fileProvider }; fileSystem.InputPaths.Clear(); fileSystem.InputPaths.Add("/A"); TestExecutionContext context = new TestExecutionContext { FileSystem = fileSystem }; TestDocument document = new TestDocument(); KeyValuePair <string, string>[] args = new KeyValuePair <string, string>[] { new KeyValuePair <string, string>(null, "B/c.txt") }; Include shortcode = new Include(); // When IShortcodeResult result = shortcode.Execute(args, string.Empty, document, context); // Then using (TextReader reader = new StreamReader(result.Stream)) { reader.ReadToEnd().ShouldBe("foo"); } }
public void RecursiveWildcardTests(string directoryPath, string[] patterns, string[] resultPaths) { // Given TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/a"); fileProvider.AddDirectory("/a/b"); fileProvider.AddDirectory("/a/b/c"); fileProvider.AddDirectory("/a/b/c/d"); fileProvider.AddDirectory("/a/b/c/d/e"); fileProvider.AddDirectory("/a/b/c/d/e/1"); fileProvider.AddDirectory("/a/b/c/d/e/1/2"); fileProvider.AddFile("/a/b/c/d/e/1/2/3.txt"); IDirectory directory = fileProvider.GetDirectory(directoryPath); // When IEnumerable <IFile> matches = Globber.GetFiles(directory, patterns); IEnumerable <IFile> matchesReversedSlash = Globber.GetFiles(directory, patterns.Select(x => x.Replace("/", "\\"))); // Then CollectionAssert.AreEquivalent(resultPaths, matches.Select(x => x.Path.FullPath)); CollectionAssert.AreEquivalent(resultPaths, matchesReversedSlash.Select(x => x.Path.FullPath)); }
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 type = typeof(TestView); var expected = new CompilationResult(type); // Act - 1 var result1 = cache.GetOrAdd(@"Areas\Finances\Views\Home\Index.cshtml", _ => expected); // Assert - 1 Assert.Same(type, result1.CompilationResult.CompiledType); // Act - 2 var result2 = cache.GetOrAdd(relativePath, ThrowsIfCalled); // Assert - 2 Assert.Same(type, result2.CompilationResult.CompiledType); }
public void AddFileVersionToPath_UpdatesEntryWhenCacheExpires_ForNonExistingFile() { // Arrange var fileProvider = new TestFileProvider(); var fileVersionProvider = new FileVersionProvider( fileProvider, new MemoryCache(new MemoryCacheOptions()), GetRequestPathBase()); // Act 1 - File does not exist var result = fileVersionProvider.AddFileVersionToPath("file.txt"); // Assert 1 Assert.Equal("file.txt", result); // Act 2 - File gets added fileProvider.AddFile("file.txt", "Hello World!"); fileProvider.GetChangeToken("file.txt").HasChanged = true; result = fileVersionProvider.AddFileVersionToPath("file.txt"); // Assert 2 Assert.Equal("file.txt?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", result); }
public void LookupFileInfo_ReturnsTrue_IfFileExists() { // Arrange var options = new StaticFileOptions(); var fileProvider = new TestFileProvider(); fileProvider.AddFile("/foo.txt", new TestFileInfo { LastModified = new DateTimeOffset(2014, 1, 2, 3, 4, 5, TimeSpan.Zero) }); var pathString = new PathString("/test"); var httpContext = new DefaultHttpContext(); httpContext.Request.Path = new PathString("/test/foo.txt"); var context = new StaticFileContext(httpContext, options, pathString, NullLogger.Instance, fileProvider, new FileExtensionContentTypeProvider()); // Act context.ValidatePath(); var result = context.LookupFileInfo(); // Assert Assert.True(result); }
public void AddFileVersionToPath_DoesNotLockFileAfterReading() { // Arrange var stream = new TestableMemoryStream(Encoding.UTF8.GetBytes("Hello World!")); var mockFile = new Mock <IFileInfo>(); mockFile.SetupGet(f => f.Exists).Returns(true); mockFile .Setup(m => m.CreateReadStream()) .Returns(stream); var fileProvider = new TestFileProvider(); fileProvider.AddFile("/hello/world", mockFile.Object); var requestPath = GetRequestPathBase(); var fileVersionProvider = GetFileVersionProvider(fileProvider); // Act var result = fileVersionProvider.AddFileVersionToPath(requestPath, "/hello/world"); // Assert Assert.True(stream.Disposed); }
public void AddFileVersionToPath_UpdatesEntryWhenCacheExpires_ForExistingFile_WithRequestPathBase() { // Arrange var fileProvider = new TestFileProvider(); var requestPath = GetRequestPathBase("/wwwroot/"); var fileVersionProvider = GetFileVersionProvider(fileProvider); fileProvider.AddFile("file.txt", "Hello World!"); // Act 1 - File exists var result = fileVersionProvider.AddFileVersionToPath(requestPath, "/wwwroot/file.txt"); // Assert 1 Assert.Equal("/wwwroot/file.txt?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk", result); // Act 2 fileProvider.DeleteFile("file.txt"); fileProvider.GetChangeToken("file.txt").HasChanged = true; result = fileVersionProvider.AddFileVersionToPath(requestPath, "/wwwroot/file.txt"); // Assert 2 Assert.Equal("/wwwroot/file.txt", result); }
public async Task CompileAsync_PrecompiledViewWithChecksum_CanReusePrecompiledViewIfContentChangesToMatch() { // Arrange var path = "/Views/Home/Index.cshtml"; var fileProvider = new TestFileProvider(); var file = fileProvider.AddFile(path, "different content"); var expected1 = new CompiledViewDescriptor(); var precompiledView = new CompiledViewDescriptor { RelativePath = path, Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[] { new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), path), }), }; var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView }); viewCompiler.Compile = _ => expected1; // Act - 1 var result = await viewCompiler.CompileAsync(path); // Assert - 1 Assert.Same(expected1, result); // Act - 2 file.Content = "some content"; fileProvider.GetChangeToken(path).HasChanged = true; result = await viewCompiler.CompileAsync(path); // Assert - 2 Assert.Same(precompiledView.Item, result.Item); }
public async Task CompileAsync_PrecompiledViewWithoutChecksumForMainSource_DoesNotSupportRecompilation() { // Arrange var path = "/Views/Home/Index.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "some content"); var precompiledView = new CompiledViewDescriptor { RelativePath = path, Item = new TestRazorCompiledItem(typeof(string), "mvc.1.0.view", path, new object[] { new RazorSourceChecksumAttribute("sha1", GetChecksum("some content"), "/Views/Some-Other-View"), }), }; var viewCompiler = GetViewCompiler(fileProvider, precompiledViews: new[] { precompiledView }); // Act - 1 var result = await viewCompiler.CompileAsync(path); // Assert - 1 Assert.Same(precompiledView.Item, result.Item); // Act - 2 fileProvider.Watch(path); fileProvider.GetChangeToken(path).HasChanged = true; result = await viewCompiler.CompileAsync(path); // Assert - 2 Assert.Same(precompiledView.Item, result.Item); // This view doesn't have checksums so it can't be recompiled. Assert.Null(result.ExpirationTokens); }
public void EmptyResultIfFileDoesNotExist() { // Given TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/A"); fileProvider.AddDirectory("/A/B"); fileProvider.AddFile("/A/B/c.txt", "foo"); TestFileSystem fileSystem = new TestFileSystem { FileProvider = fileProvider }; fileSystem.InputPaths.Clear(); fileSystem.InputPaths.Add("/A"); TestExecutionContext context = new TestExecutionContext { FileSystem = fileSystem }; context.TestLoggerProvider.ThrowLogLevel = LogLevel.Error; TestDocument document = new TestDocument(); KeyValuePair <string, string>[] args = new KeyValuePair <string, string>[] { new KeyValuePair <string, string>(null, "B/d.txt") }; IncludeShortcode shortcode = new IncludeShortcode(); // When IDocument result = shortcode.Execute(args, string.Empty, document, context); // Then result.ShouldBeOfType <TestDocument>().Content.ShouldBeEmpty(); }
public void GetOrAdd_ExpiresEntriesAfterOneMinute() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "some content"); var clock = new Mock<ISystemClock>(); var utcNow = DateTimeOffset.UtcNow; clock.SetupGet(c => c.UtcNow) .Returns(() => utcNow); var options = new MemoryCacheOptions { Clock = clock.Object }; using (var chunkTreeCache = new DefaultChunkTreeCache(fileProvider, options)) { var chunkTree1 = new ChunkTree(); var chunkTree2 = new ChunkTree(); // Act 1 var result1 = chunkTreeCache.GetOrAdd(path, fileInfo => chunkTree1); // Assert 1 Assert.Same(chunkTree1, result1); // Act 2 utcNow = utcNow.AddSeconds(59); var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => { throw new Exception("Shouldn't be called."); }); // Assert 2 Assert.Same(chunkTree1, result2); // Act 3 utcNow = utcNow.AddSeconds(65); var result3 = chunkTreeCache.GetOrAdd(path, fileInfo => chunkTree2); // Assert 3 Assert.Same(chunkTree2, result3); } }
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 type = typeof(TestView); var expected = UncachedCompilationResult.Successful(type, "hello world"); // Act - 1 var result1 = cache.GetOrAdd(@"Areas\Finances\Views\Home\Index.cshtml", _ => expected); // Assert - 1 var compilationResult = Assert.IsType<UncachedCompilationResult>(result1.CompilationResult); Assert.Same(expected, compilationResult); Assert.Same(type, compilationResult.CompiledType); // Act - 2 var result2 = cache.GetOrAdd(relativePath, ThrowsIfCalled); // Assert - 2 Assert.Same(type, result2.CompilationResult.CompiledType); }
public void SkipsHttpsCompression_IfNotMatched() { var options = new StaticFileOptions(); var fileProvider = new TestFileProvider(); fileProvider.AddFile("/foo.txt", new TestFileInfo { LastModified = new DateTimeOffset(2014, 1, 2, 3, 4, 5, TimeSpan.Zero) }); var pathString = new PathString("/test"); var httpContext = new DefaultHttpContext(); var httpsCompressionFeature = new TestHttpsCompressionFeature(); httpContext.Features.Set <IHttpsCompressionFeature>(httpsCompressionFeature); httpContext.Request.Path = new PathString("/test/bar.txt"); var context = new StaticFileContext(httpContext, options, pathString, NullLogger.Instance, fileProvider, new FileExtensionContentTypeProvider()); context.ValidatePath(); var result = context.LookupFileInfo(); Assert.False(result); Assert.Equal(HttpsCompressionMode.Default, httpsCompressionFeature.Mode); }
public async Task IncludesFileRelativeToSource() { // Given TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/A"); fileProvider.AddDirectory("/A/B"); fileProvider.AddDirectory("/A/D"); fileProvider.AddFile("/A/B/c.txt", "foo"); TestFileSystem fileSystem = new TestFileSystem { FileProvider = fileProvider }; fileSystem.InputPaths.Clear(); fileSystem.InputPaths.Add("/A"); TestExecutionContext context = new TestExecutionContext { FileSystem = fileSystem }; TestDocument document = new TestDocument(new FilePath("/A/D/x.txt"), (FilePath)null); KeyValuePair <string, string>[] args = new KeyValuePair <string, string>[] { new KeyValuePair <string, string>(null, "../B/c.txt") }; IncludeShortcode shortcode = new IncludeShortcode(); // When TestDocument result = (TestDocument)await shortcode.ExecuteAsync(args, string.Empty, document, context); // Then result.Content.ShouldBe("foo"); }
public void OnProvidersExecuting_ValidatesChecksum_RejectsPageWhenContentDoesntMatch() { // Arrange var descriptors = new[] { CreateVersion_2_1_Descriptor("/Pages/About.cshtml", metadata: new object[] { new RazorSourceChecksumAttribute("SHA1", GetChecksum("some content"), "/Pages/About.cshtml"), }), }; var fileProvider = new TestFileProvider(); fileProvider.AddFile("/Pages/About.cshtml", "some other content"); var provider = CreateProvider(descriptors: descriptors, fileProvider: fileProvider); var context = new PageRouteModelProviderContext(); // Act provider.OnProvidersExecuting(context); // Assert Assert.Empty(context.RouteModels); }
public void GetOrAdd_UpdatesCache_IfFileExpirationTriggerExpires() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "test content"); var chunkTreeCache = new DefaultChunkTreeCache(fileProvider); var expected1 = new ChunkTree(); var expected2 = new ChunkTree(); // Act 1 var result1 = chunkTreeCache.GetOrAdd(path, fileInfo => expected1); // Assert 1 Assert.Same(expected1, result1); // Act 2 fileProvider.GetTrigger(path).IsExpired = true; var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => expected2); // Assert 2 Assert.Same(expected2, result2); }
public async Task CompileAsync_DoesNotInvalidCache_IfChangeTokenChanges() { // Arrange var path = "/Views/Home/Index.cshtml"; var fileProvider = new TestFileProvider(); var fileInfo = fileProvider.AddFile(path, "some content"); var viewCompiler = GetViewCompiler(fileProvider); var changeToken = fileProvider.Watch(path); // Act 1 var result1 = await viewCompiler.CompileAsync(path); // Assert 1 Assert.NotNull(result1.ViewAttribute); // Act 2 fileProvider.DeleteFile(path); fileProvider.GetChangeToken(path).HasChanged = true; viewCompiler.Compile = _ => throw new Exception("Can't call me"); var result2 = await viewCompiler.CompileAsync(path); // Assert 2 Assert.Same(result1, result2); }
public async Task EmptyResultIfFileDoesNotExist() { // Given TestFileProvider fileProvider = new TestFileProvider(); fileProvider.AddDirectory("/"); fileProvider.AddDirectory("/A"); fileProvider.AddDirectory("/A/B"); fileProvider.AddFile("/A/B/c.txt", "foo"); TestFileSystem fileSystem = new TestFileSystem { FileProvider = fileProvider }; fileSystem.InputPaths.Clear(); fileSystem.InputPaths.Add("/A"); TestExecutionContext context = new TestExecutionContext { FileSystem = fileSystem, Logger = new TestLogger(LogLevel.Error) }; TestDocument document = new TestDocument(); KeyValuePair <string, string>[] args = new KeyValuePair <string, string>[] { new KeyValuePair <string, string>(null, "B/d.txt") }; IncludeShortcode shortcode = new IncludeShortcode(); // When TestDocument result = (TestDocument)await shortcode.ExecuteAsync(args, string.Empty, document, context); // Then result.Content.ShouldBeEmpty(); }
public void GetOrAdd_ReturnsRuntimeCompiledAndPrecompiledViews() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(fileProvider, _precompiledViews); var expected = CompilationResult.Successful(typeof(TestView)); // Act 1 var result1 = cache.GetOrAdd(ViewPath, _ => expected); // Assert 1 Assert.Same(expected, result1.CompilationResult); // Act 2 var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled); // Assert 2 Assert.NotSame(CompilerCacheResult.FileNotFound, result2); Assert.Same(typeof(TestView), result2.CompilationResult.CompiledType); // Act 3 var result3 = cache.GetOrAdd(PrecompiledViewsPath, ThrowsIfCalled); // Assert 3 Assert.NotSame(CompilerCacheResult.FileNotFound, result2); Assert.Same(typeof(PreCompile), result3.CompilationResult.CompiledType); }
public void GetInheritedChunks_ReadsChunksFromGlobalFilesInPath() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(@"/Views/accounts/_ViewImports.cshtml", "@using AccountModels"); fileProvider.AddFile(@"/Views/Shared/_ViewImports.cshtml", "@inject SharedHelper Shared"); fileProvider.AddFile(@"/Views/home/_ViewImports.cshtml", "@using MyNamespace"); fileProvider.AddFile(@"/Views/_ViewImports.cshtml", @"@inject MyHelper<TModel> Helper @inherits MyBaseType @{ Layout = ""test.cshtml""; } "); var defaultChunks = new Chunk[] { new InjectChunk("MyTestHtmlHelper", "Html"), new UsingChunk { Namespace = "AppNamespace.Model" }, }; var cache = new DefaultChunkTreeCache(fileProvider); using (var host = new MvcRazorHost(cache, new TagHelperDescriptorResolver(designTime: false))) { var utility = new ChunkInheritanceUtility(host, cache, defaultChunks); // Act var chunkTreeResults = utility.GetInheritedChunkTreeResults( PlatformNormalizer.NormalizePath(@"Views\home\Index.cshtml")); // Assert Assert.Collection(chunkTreeResults, chunkTreeResult => { var viewImportsPath = @"/Views/_ViewImports.cshtml"; Assert.Collection(chunkTreeResult.ChunkTree.Children, chunk => { Assert.IsType<LiteralChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { var injectChunk = Assert.IsType<InjectChunk>(chunk); Assert.Equal("MyHelper<TModel>", injectChunk.TypeName); Assert.Equal("Helper", injectChunk.MemberName); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { Assert.IsType<LiteralChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { var setBaseTypeChunk = Assert.IsType<SetBaseTypeChunk>(chunk); Assert.Equal("MyBaseType", setBaseTypeChunk.TypeName); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { Assert.IsType<LiteralChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { Assert.IsType<StatementChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { Assert.IsType<LiteralChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }); Assert.Equal(viewImportsPath, chunkTreeResult.FilePath); }, chunkTreeResult => { var viewImportsPath = "/Views/home/_ViewImports.cshtml"; Assert.Collection(chunkTreeResult.ChunkTree.Children, chunk => { Assert.IsType<LiteralChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { var usingChunk = Assert.IsType<UsingChunk>(chunk); Assert.Equal("MyNamespace", usingChunk.Namespace); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }, chunk => { Assert.IsType<LiteralChunk>(chunk); Assert.Equal(viewImportsPath, chunk.Start.FilePath); }); Assert.Equal(viewImportsPath, chunkTreeResult.FilePath); }); } }
public void MergeInheritedChunks_MergesDefaultInheritedChunks() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(@"/Views/_ViewImports.cshtml", "@inject DifferentHelper<TModel> Html"); var cache = new DefaultChunkTreeCache(fileProvider); using (var host = new MvcRazorHost(cache, new TagHelperDescriptorResolver(designTime: false))) { var defaultChunks = new Chunk[] { new InjectChunk("MyTestHtmlHelper", "Html"), new UsingChunk { Namespace = "AppNamespace.Model" }, }; var inheritedChunkTrees = new ChunkTree[] { new ChunkTree { Children = new Chunk[] { new UsingChunk { Namespace = "InheritedNamespace" }, new LiteralChunk { Text = "some text" } } }, new ChunkTree { Children = new Chunk[] { new UsingChunk { Namespace = "AppNamespace.Model" }, } } }; var utility = new ChunkInheritanceUtility(host, cache, defaultChunks); var chunkTree = new ChunkTree(); // Act utility.MergeInheritedChunkTrees(chunkTree, inheritedChunkTrees, "dynamic"); // Assert Assert.Collection(chunkTree.Children, chunk => Assert.Same(defaultChunks[1], chunk), chunk => Assert.Same(inheritedChunkTrees[0].Children[0], chunk), chunk => Assert.Same(defaultChunks[0], chunk)); } }
public void Compile_DoesNotThrow_IfFileCannotBeRead() { // Arrange var path = "some-relative-path"; var content = $@" #line 1 ""{path}"" this should fail"; var applicationEnvironment = GetApplicationEnvironment(); var accessor = GetLoadContextAccessor(); var libraryExporter = GetLibraryExporter(); var compilerOptionsProvider = new Mock<ICompilerOptionsProvider>(); compilerOptionsProvider.Setup(p => p.GetCompilerOptions(applicationEnvironment.ApplicationName, applicationEnvironment.RuntimeFramework, applicationEnvironment.Configuration)) .Returns(new CompilerOptions()); var mvcRazorHost = Mock.Of<IMvcRazorHost>(); var mockFileInfo = new Mock<IFileInfo>(); mockFileInfo.Setup(f => f.CreateReadStream()) .Throws(new Exception()); var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, mockFileInfo.Object); var compilationService = new RoslynCompilationService(applicationEnvironment, accessor, libraryExporter, compilerOptionsProvider.Object, mvcRazorHost, GetOptions(fileProvider)); var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType<CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(path, compilationFailure.SourceFilePath); Assert.Null(compilationFailure.SourceFileContent); }
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 GetInheritedChunks_ReturnsEmptySequenceIfNoGlobalsArePresent() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(@"/_ViewImports.cs", string.Empty); fileProvider.AddFile(@"/Views/_Layout.cshtml", string.Empty); fileProvider.AddFile(@"/Views/home/_not-viewimports.cshtml", string.Empty); var cache = new DefaultChunkTreeCache(fileProvider); using (var host = new MvcRazorHost(cache, new TagHelperDescriptorResolver(designTime: false))) { var defaultChunks = new Chunk[] { new InjectChunk("MyTestHtmlHelper", "Html"), new UsingChunk { Namespace = "AppNamespace.Model" }, }; var utility = new ChunkInheritanceUtility(host, cache, defaultChunks); // Act var chunkTrees = utility.GetInheritedChunkTreeResults(PlatformNormalizer.NormalizePath(@"Views\home\Index.cshtml")); // Assert Assert.Empty(chunkTrees); } }
public void Compile_DoesNotThrow_IfFileCannotBeRead() { // Arrange var path = "some-relative-path"; var content = $@" #line 1 ""{path}"" this should fail"; var mockFileInfo = new Mock<IFileInfo>(); mockFileInfo.Setup(f => f.CreateReadStream()) .Throws(new Exception()); var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, mockFileInfo.Object); var compilationService = new DefaultRoslynCompilationService( GetDependencyContext(), GetOptions(), GetFileProviderAccessor(), NullLoggerFactory.Instance); var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path); // Act var result = compilationService.Compile(relativeFileInfo, content); // Assert Assert.IsType<CompilationResult>(result); Assert.Null(result.CompiledType); var compilationFailure = Assert.Single(result.CompilationFailures); Assert.Equal(path, compilationFailure.SourceFilePath); Assert.Null(compilationFailure.SourceFileContent); }
public void GetCompilationFailedResult_ReturnsCompilationResult_WithGroupedMessages() { // Arrange var viewPath = "Views/Home/Index"; var generatedCodeFileName = "Generated Code"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(viewPath, "view-content"); var options = new RazorViewEngineOptions(); options.FileProviders.Add(fileProvider); var compilationService = new DefaultRoslynCompilationService( GetDependencyContext(), options, GetFileProviderAccessor(fileProvider), NullLoggerFactory.Instance); var assemblyName = "random-assembly-name"; var diagnostics = new[] { Diagnostic.Create( GetDiagnosticDescriptor("message-1"), Location.Create( viewPath, new TextSpan(10, 5), new LinePositionSpan(new LinePosition(10, 1), new LinePosition(10, 2)))), Diagnostic.Create( GetDiagnosticDescriptor("message-2"), Location.Create( assemblyName, new TextSpan(1, 6), new LinePositionSpan(new LinePosition(1, 2), new LinePosition(3, 4)))), Diagnostic.Create( GetDiagnosticDescriptor("message-3"), Location.Create( viewPath, new TextSpan(40, 50), new LinePositionSpan(new LinePosition(30, 5), new LinePosition(40, 12)))), }; // Act var compilationResult = compilationService.GetCompilationFailedResult( viewPath, "compilation-content", assemblyName, diagnostics); // Assert Assert.Collection(compilationResult.CompilationFailures, failure => { Assert.Equal(viewPath, failure.SourceFilePath); Assert.Equal("view-content", failure.SourceFileContent); Assert.Collection(failure.Messages, message => { Assert.Equal("message-1", message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(11, message.StartLine); Assert.Equal(2, message.StartColumn); Assert.Equal(11, message.EndLine); Assert.Equal(3, message.EndColumn); }, message => { Assert.Equal("message-3", message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(31, message.StartLine); Assert.Equal(6, message.StartColumn); Assert.Equal(41, message.EndLine); Assert.Equal(13, message.EndColumn); }); }, failure => { Assert.Equal(generatedCodeFileName, failure.SourceFilePath); Assert.Equal("compilation-content", failure.SourceFileContent); Assert.Collection(failure.Messages, message => { Assert.Equal("message-2", message.Message); Assert.Equal(assemblyName, message.SourceFilePath); Assert.Equal(2, message.StartLine); Assert.Equal(3, message.StartColumn); Assert.Equal(4, message.EndLine); Assert.Equal(5, message.EndColumn); }); }); }
public void GetOrAdd_ReturnsNewResult_IfAncestorViewImportsWereModified(string globalImportPath) { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(fileProvider); var expected1 = UncachedCompilationResult.Successful(typeof(TestView), "hello world"); var expected2 = UncachedCompilationResult.Successful(typeof(DifferentView), "different content"); // Act 1 var result1 = cache.GetOrAdd(ViewPath, _ => expected1); // Assert 1 Assert.NotSame(CompilerCacheResult.FileNotFound, result1); Assert.Same(expected1, result1.CompilationResult); // Act 2 // Verify we're getting cached results. var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled); // Assert 2 Assert.NotSame(CompilerCacheResult.FileNotFound, result2); Assert.Same(expected1.CompiledType, result2.CompilationResult.CompiledType); // Act 3 fileProvider.GetChangeToken(globalImportPath).HasChanged = true; var result3 = cache.GetOrAdd(ViewPath, _ => expected2); // Assert 2 Assert.NotSame(CompilerCacheResult.FileNotFound, result3); Assert.Same(expected2, result3.CompilationResult); }
public void GetOrAdd_ReturnsSuccessfulCompilationResultIfTriggerExpires() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(fileProvider); // Act and Assert - 1 Assert.Throws<InvalidTimeZoneException>(() => cache.GetOrAdd(ViewPath, _ => { throw new InvalidTimeZoneException(); })); // Act - 2 fileProvider.GetChangeToken(ViewPath).HasChanged = true; var result = cache.GetOrAdd(ViewPath, _ => new CompilationResult(typeof(TestView))); // Assert - 2 Assert.IsType<TestView>(result.PageFactory()); }
public void GetCompilationFailedResult_ReturnsCompilationResult_WithGroupedMessages() { // Arrange var viewPath = @"views/index.razor"; var viewImportsPath = @"views/global.import.cshtml"; var host = Mock.Of<IMvcRazorHost>(); var fileProvider = new TestFileProvider(); var file = fileProvider.AddFile(viewPath, "View Content"); fileProvider.AddFile(viewImportsPath, "Global Import Content"); var relativeFileInfo = new RelativeFileInfo(file, viewPath); var razorService = new RazorCompilationService( Mock.Of<ICompilationService>(), Mock.Of<IMvcRazorHost>(), GetOptions(fileProvider)); var errors = new[] { new RazorError("message-1", new SourceLocation(1, 2, 17)), new RazorError("message-2", new SourceLocation(viewPath, 1, 4, 6), 7), new RazorError { Message = "message-3" }, new RazorError("message-4", new SourceLocation(viewImportsPath, 1, 3, 8), 4), }; // Act var result = razorService.GetCompilationFailedResult(relativeFileInfo, errors); // Assert Assert.NotNull(result.CompilationFailures); Assert.Collection(result.CompilationFailures, failure => { Assert.Equal(viewPath, failure.SourceFilePath); Assert.Equal("View Content", failure.SourceFileContent); Assert.Collection(failure.Messages, message => { Assert.Equal(errors[0].Message, message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(3, message.StartLine); Assert.Equal(17, message.StartColumn); Assert.Equal(3, message.EndLine); Assert.Equal(18, message.EndColumn); }, message => { Assert.Equal(errors[1].Message, message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(5, message.StartLine); Assert.Equal(6, message.StartColumn); Assert.Equal(5, message.EndLine); Assert.Equal(13, message.EndColumn); }, message => { Assert.Equal(errors[2].Message, message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(0, message.StartLine); Assert.Equal(-1, message.StartColumn); Assert.Equal(0, message.EndLine); Assert.Equal(0, message.EndColumn); }); }, failure => { Assert.Equal(viewImportsPath, failure.SourceFilePath); Assert.Equal("Global Import Content", failure.SourceFileContent); Assert.Collection(failure.Messages, message => { Assert.Equal(errors[3].Message, message.Message); Assert.Equal(viewImportsPath, message.SourceFilePath); Assert.Equal(4, message.StartLine); Assert.Equal(8, message.StartColumn); Assert.Equal(4, message.EndLine); Assert.Equal(12, message.EndColumn); }); }); }
public void GetOrAdd_UpdatesCacheWithValue_IfFileWasAdded() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); var codeTreeCache = new DefaultCodeTreeCache(fileProvider); var expected = new CodeTree(); // Act 1 var result1 = codeTreeCache.GetOrAdd(path, fileInfo => { throw new Exception("Shouldn't be called."); }); // Assert 1 Assert.Null(result1); // Act 2 fileProvider.AddFile(path, "test content"); fileProvider.GetTrigger(path).IsExpired = true; var result2 = codeTreeCache.GetOrAdd(path, fileInfo => expected); // Assert 2 Assert.Same(expected, result2); }
public void MergeInheritedChunks_MergesDefaultInheritedChunks() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(@"Views\_ViewImports.cshtml", "@inject DifferentHelper<TModel> Html"); var cache = new DefaultChunkTreeCache(fileProvider); var host = new MvcRazorHost(cache); var defaultChunks = new Chunk[] { new InjectChunk("MyTestHtmlHelper", "Html"), new UsingChunk { Namespace = "AppNamespace.Model" }, }; var inheritedChunkTrees = new ChunkTree[] { new ChunkTree { Chunks = new Chunk[] { new UsingChunk { Namespace = "InheritedNamespace" }, new LiteralChunk { Text = "some text" } } }, new ChunkTree { Chunks = new Chunk[] { new UsingChunk { Namespace = "AppNamespace.Model" }, } } }; var utility = new ChunkInheritanceUtility(host, cache, defaultChunks); var chunkTree = new ChunkTree(); // Act utility.MergeInheritedChunkTrees(chunkTree, inheritedChunkTrees, "dynamic"); // Assert Assert.Equal(3, chunkTree.Chunks.Count); Assert.Same(inheritedChunkTrees[0].Chunks[0], chunkTree.Chunks[0]); Assert.Same(inheritedChunkTrees[1].Chunks[0], chunkTree.Chunks[1]); Assert.Same(defaultChunks[0], chunkTree.Chunks[2]); }
public void GetOrAdd_UpdatesCacheWithNullValue_IfFileWasDeleted() { // Arrange var path = @"Views\Home\_ViewStart.cshtml"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(path, "test content"); using (var chunkTreeCache = new DefaultChunkTreeCache(fileProvider)) { var expected1 = new ChunkTree(); // Act 1 var result1 = chunkTreeCache.GetOrAdd(path, fileInfo => expected1); // Assert 1 Assert.Same(expected1, result1); // Act 2 fileProvider.DeleteFile(path); fileProvider.GetChangeToken(path).HasChanged = true; var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => { throw new Exception("Shouldn't be called."); }); // Assert 2 Assert.Null(result2); } }
public void GetOrAdd_ReturnsFileNotFoundIfFileWasDeleted() { // Arrange var fileProvider = new TestFileProvider(); fileProvider.AddFile(ViewPath, "some content"); var cache = new CompilerCache(fileProvider); var type = typeof(TestView); var expected = UncachedCompilationResult.Successful(type, "hello world"); // Act 1 var result1 = cache.GetOrAdd(ViewPath, _ => expected); // Assert 1 Assert.NotSame(CompilerCacheResult.FileNotFound, result1); Assert.Same(expected, result1.CompilationResult); // 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.Same(CompilerCacheResult.FileNotFound, result2); Assert.Null(result2.CompilationResult); }
public void GetCompilationFailedResult_ReturnsCompilationResult_WithGroupedMessages() { // Arrange var viewPath = "Views/Home/Index"; var generatedCodeFileName = "Generated Code"; var fileProvider = new TestFileProvider(); fileProvider.AddFile(viewPath, "view-content"); var options = new Mock<IOptions<RazorViewEngineOptions>>(); options.SetupGet(o => o.Options) .Returns(new RazorViewEngineOptions { FileProvider = fileProvider }); var compilationService = new RoslynCompilationService( GetApplicationEnvironment(), GetLoadContextAccessor(), GetLibraryExporter(), Mock.Of<ICompilerOptionsProvider>(), Mock.Of<IMvcRazorHost>(), options.Object); var assemblyName = "random-assembly-name"; var diagnostics = new[] { Diagnostic.Create( GetDiagnosticDescriptor("message-1"), Location.Create( viewPath, new TextSpan(10, 5), new LinePositionSpan(new LinePosition(10, 1), new LinePosition(10, 2)))), Diagnostic.Create( GetDiagnosticDescriptor("message-2"), Location.Create( assemblyName, new TextSpan(1, 6), new LinePositionSpan(new LinePosition(1, 2), new LinePosition(3, 4)))), Diagnostic.Create( GetDiagnosticDescriptor("message-3"), Location.Create( viewPath, new TextSpan(40, 50), new LinePositionSpan(new LinePosition(30, 5), new LinePosition(40, 12)))), }; // Act var compilationResult = compilationService.GetCompilationFailedResult( viewPath, "compilation-content", assemblyName, diagnostics); // Assert Assert.Collection(compilationResult.CompilationFailures, failure => { Assert.Equal(viewPath, failure.SourceFilePath); Assert.Equal("view-content", failure.SourceFileContent); Assert.Collection(failure.Messages, message => { Assert.Equal("message-1", message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(11, message.StartLine); Assert.Equal(2, message.StartColumn); Assert.Equal(11, message.EndLine); Assert.Equal(3, message.EndColumn); }, message => { Assert.Equal("message-3", message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(31, message.StartLine); Assert.Equal(6, message.StartColumn); Assert.Equal(41, message.EndLine); Assert.Equal(13, message.EndColumn); }); }, failure => { Assert.Equal(generatedCodeFileName, failure.SourceFilePath); Assert.Equal("compilation-content", failure.SourceFileContent); Assert.Collection(failure.Messages, message => { Assert.Equal("message-2", message.Message); Assert.Equal(assemblyName, message.SourceFilePath); Assert.Equal(2, message.StartLine); Assert.Equal(3, message.StartColumn); Assert.Equal(4, message.EndLine); Assert.Equal(5, message.EndColumn); }); }); }
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); }