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 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);
        }
Example #3
0
        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 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);
        }
Example #5
0
        public void GetOrAdd_ReturnsFileNotFoundResult_IfFileIsNotFoundInFileSystem()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var cache = new CompilerCache(fileProvider);

            // Act
            var result = cache.GetOrAdd("/some/path", ThrowsIfCalled);

            // Assert
            Assert.False(result.Success);
        }
        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]);
        }
Example #7
0
        public void GetOrAdd_ReturnsFileNotFoundResult_IfFileIsNotFoundInFileSystem()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var cache = new CompilerCache(Enumerable.Empty<RazorFileInfoCollection>(), TestLoadContext, fileProvider);

            // Act
            var result = cache.GetOrAdd("/some/path", ThrowsIfCalled);

            // Assert
            Assert.Same(CompilerCacheResult.FileNotFound, result);
            Assert.Null(result.CompilationResult);
        }
Example #8
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);
        }
        public void FileProvider_ReturnsInstanceIfExactlyOneFileProviderIsSpecified()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var options = new RazorViewEngineOptions();
            options.FileProviders.Add(fileProvider);
            var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
            optionsAccessor.SetupGet(o => o.Value).Returns(options);
            var fileProviderAccessor = new DefaultRazorViewEngineFileProviderAccessor(optionsAccessor.Object);

            // Act
            var actual = fileProviderAccessor.FileProvider;

            // Assert
            Assert.Same(fileProvider, actual);
        }
Example #10
0
        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 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 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 DoubleWildcardShouldMatchZeroOrMorePathSegments()
            {
                // Given
                TestFileProvider fileProvider = new TestFileProvider();

                fileProvider.AddDirectory("/");
                fileProvider.AddDirectory("/root");
                fileProvider.AddDirectory("/root/a");
                fileProvider.AddDirectory("/root/a/b");
                fileProvider.AddDirectory("/root/d");
                fileProvider.AddFile("/root/a/x.txt");
                fileProvider.AddFile("/root/a/b/x.txt");
                fileProvider.AddFile("/root/d/x.txt");
                IDirectory directory = fileProvider.GetDirectory("/");

                // When
                IEnumerable <IFile> matches = Globber.GetFiles(directory, new[] { "root/{a,}/**/x.txt" });

                // Then
                matches.Select(x => x.Path.FullPath).ShouldBe(
                    new[] { "/root/a/x.txt", "/root/a/b/x.txt", "/root/d/x.txt" }, true);
            }
        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);
        }
        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);
        }
Example #16
0
        private static TestRazorViewCompiler GetViewCompiler(
            TestFileProvider fileProvider = null,
            Action <RoslynCompilationContext> compilationCallback = null,
            RazorReferenceManager referenceManager          = null,
            IList <CompiledViewDescriptor> precompiledViews = null)
        {
            fileProvider = fileProvider ?? new TestFileProvider();
            var accessor = Mock.Of <IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);

            compilationCallback = compilationCallback ?? (_ => { });
            var options = Options.Create(new RazorViewEngineOptions());

            if (referenceManager == null)
            {
                var applicationPartManager = new ApplicationPartManager();
                var assembly = typeof(RazorViewCompilerTest).Assembly;
                applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
                applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());

                referenceManager = new DefaultRazorReferenceManager(applicationPartManager, options);
            }

            precompiledViews = precompiledViews ?? Array.Empty <CompiledViewDescriptor>();

            var hostingEnvironment = Mock.Of <IHostingEnvironment>(e => e.ContentRootPath == "BasePath");
            var fileSystem         = new FileProviderRazorProjectFileSystem(accessor, hostingEnvironment);
            var projectEngine      = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
            {
                RazorExtensions.Register(builder);
            });
            var viewCompiler = new TestRazorViewCompiler(
                fileProvider,
                projectEngine,
                new CSharpCompiler(referenceManager, hostingEnvironment),
                compilationCallback,
                precompiledViews);

            return(viewCompiler);
        }
Example #17
0
            public async Task IncludesDocumentsFromDependencies()
            {
                // Given
                Bootstrapper bootstrapper = Bootstrapper.Factory.CreateWeb(Array.Empty <string>());

                bootstrapper.AddSetting(WebKeys.DataFiles, "x/**/*.json");
                bootstrapper.BuildPipeline("Test", builder => builder
                                           .WithInputReadFiles("a/**/*.json")
                                           .AsDependencyOf(nameof(Data)));
                TestFileProvider fileProvider = new TestFileProvider
                {
                    { "/input/a/b/c.json", "{ \"Foo\": \"Bar\" }" },
                    { "/input/x/y/z.json", "{ \"Foo\": \"Buz\" }" }
                };

                // When
                BootstrapperTestResult result = await bootstrapper.RunTestAsync(fileProvider);

                // Then
                result.ExitCode.ShouldBe((int)ExitCode.Normal);
                result.Outputs[nameof(Data)][Phase.Process].Select(x => x["Foo"]).ShouldBe(new[] { "Bar", "Buz" }, true);
            }
Example #18
0
        public void EnumerateFiles_ReturnsCshtmlFiles()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("File1.cshtml", "content");
            var file2        = fileProvider.AddFile("File2.js", "content");
            var file3        = fileProvider.AddFile("File3.cshtml", "content");

            fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });

            var accessor = Mock.Of <IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);

            var razorProject = new FileProviderRazorProject(accessor);

            // Act
            var razorFiles = razorProject.EnumerateItems("/");

            // Assert
            Assert.Collection(razorFiles.OrderBy(f => f.FilePath),
                              file => Assert.Equal("/File1.cshtml", file.FilePath),
                              file => Assert.Equal("/File3.cshtml", file.FilePath));
        }
Example #19
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);
        }
Example #20
0
            public async Task DoesNotApplyDirectoryMetadataIfSettingIsFalse()
            {
                // Given
                Bootstrapper bootstrapper = Bootstrapper.Factory
                                            .CreateWeb(Array.Empty <string>())
                                            .AddSetting(WebKeys.ApplyDirectoryMetadata, false);
                TestFileProvider fileProvider = new TestFileProvider
                {
                    { "/input/a/b/c.json", "{ \"Foo\": \"Bar\" }" },
                    { "/input/a/_directory.json", "{ \"Fizz\": \"Buzz\" }" }
                };

                // When
                BootstrapperTestResult result = await bootstrapper.RunTestAsync(fileProvider);

                // Then
                result.ExitCode.ShouldBe((int)ExitCode.Normal);
                IDocument document = result.Outputs[nameof(Data)][Phase.Process].ShouldHaveSingleItem();

                document["Foo"].ShouldBe("Bar");
                document.ContainsKey("Fizz").ShouldBeFalse();
            }
Example #21
0
            public async Task ProcessesJsonSidecarFileWithDifferentExtension()
            {
                // Given
                Bootstrapper bootstrapper = Bootstrapper.Factory.CreateWeb(Array.Empty <string>());

                bootstrapper.AddSetting(WebKeys.DataFiles, "**/*.foo");
                TestFileProvider fileProvider = new TestFileProvider
                {
                    { "/input/a/b/c.foo", "Foobar" },
                    { "/input/a/b/_c.json", "{ \"Fizz\": \"Buzz\" }" }
                };

                // When
                BootstrapperTestResult result = await bootstrapper.RunTestAsync(fileProvider);

                // Then
                result.ExitCode.ShouldBe((int)ExitCode.Normal);
                IDocument document = result.Outputs[nameof(Data)][Phase.Process].ShouldHaveSingleItem();

                document["Fizz"].ShouldBe("Buzz");
                (await document.GetContentStringAsync()).ShouldBe("Foobar");
            }
Example #22
0
        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);
        }
Example #23
0
        public async Task GetAsync_Sample()
        {
            var requestUri = new Uri("users/test", UriKind.Relative);
            var json       = TestFileProvider.ReadText("user.json");

            clientContext.MockHttpMessageHandler.SetResponse(requestUri, json);

            var user = await client.GetAsync("test");

            Assert.IsNotNull(user);

            var expected = new UserResult
            {
                Id        = 7,
                Username  = "******",
                FullName  = "",
                Email     = "",
                AvatarUrl = "https://secure.gravatar.com/avatar/bb11777b425ba7229a182f446783203d"
            };

            ObjectTreeAssert.AreEqual(expected, user);
        }
        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.GetChangeToken(path).HasChanged = true;
            var result2 = chunkTreeCache.GetOrAdd(path, fileInfo => expected);

            // Assert 2
            Assert.Same(expected, result2);
        }
        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);
        }
Example #26
0
        private TestCompiledPageRouteModelProvider CreateProvider(
            RazorPagesOptions options = null,
            IList <CompiledViewDescriptor> descriptors = null,
            TestFileProvider fileProvider = null)
        {
            options      = options ?? new RazorPagesOptions();
            fileProvider = fileProvider ?? new TestFileProvider();
            var project = new FileProviderRazorProject(
                Mock.Of <IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider),
                Mock.Of <IHostingEnvironment>(e => e.ContentRootPath == "BasePath"));
            var templateEngine = new RazorTemplateEngine(RazorEngine.Create(), project);

            var provider = new TestCompiledPageRouteModelProvider(
                new ApplicationPartManager(),
                Options.Create(options),
                templateEngine,
                NullLogger <CompiledPageRouteModelProvider> .Instance);

            provider.Descriptors.AddRange(descriptors ?? Array.Empty <CompiledViewDescriptor>());

            return(provider);
        }
Example #27
0
        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);
        }
Example #28
0
        public async Task CompileAsync_ReturnsPrecompiledViews()
        {
            // Arrange
            var path         = "/Views/Home/Index.cshtml";
            var fileProvider = new TestFileProvider();

            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);
        }
        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);
        }
Example #30
0
            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 OnProvidersExecuting_DiscoversFilesUnderBasePath()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var dir1         = fileProvider.AddDirectoryContent("/Pages",
                                                                new[]
            {
                fileProvider.AddFile("/Pages/Index.cshtml", "@page"),
                fileProvider.AddFile("/Pages/_Layout.cshtml", "@page")
            });
            var dir2 = fileProvider.AddDirectoryContent("/NotPages",
                                                        new[]
            {
                fileProvider.AddFile("/NotPages/Index.cshtml", "@page"),
                fileProvider.AddFile("/NotPages/_Layout.cshtml", "@page")
            });
            var rootFile = fileProvider.AddFile("/Index.cshtml", "@page");

            fileProvider.AddDirectoryContent("/", new IFileInfo[] { rootFile, dir1, dir2 });

            var project = new TestRazorProject(fileProvider);

            var optionsManager = Options.Create(new RazorPagesOptions());

            optionsManager.Value.RootDirectory = "/Pages";
            var provider = new RazorProjectPageRouteModelProvider(project, optionsManager, NullLoggerFactory.Instance);
            var context  = new PageRouteModelProviderContext();

            // Act
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/Index.cshtml", model.RelativePath);
            });
        }
Example #32
0
            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 OnProvidersExecuting_ReturnsPagesWithPageDirective()
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var file1        = fileProvider.AddFile("/Pages/Home.cshtml", "@page");
            var file2        = fileProvider.AddFile("/Pages/Test.cshtml", "Hello world");

            var dir1 = fileProvider.AddDirectoryContent("/Pages", new IFileInfo[] { file1, file2 });

            fileProvider.AddDirectoryContent("/", new[] { dir1 });

            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
            provider.OnProvidersExecuting(context);

            // Assert
            Assert.Collection(context.RouteModels,
                              model =>
            {
                Assert.Equal("/Pages/Home.cshtml", model.RelativePath);
                Assert.Equal("/Pages/Home", model.ViewEnginePath);
                Assert.Collection(model.Selectors,
                                  selector => Assert.Equal("Pages/Home", selector.AttributeRouteModel.Template));
                Assert.Collection(model.RouteValues.OrderBy(k => k.Key),
                                  kvp =>
                {
                    Assert.Equal("page", kvp.Key);
                    Assert.Equal("/Pages/Home", kvp.Value);
                });
            });
        }
        private static TestRazorViewCompiler GetViewCompiler(
            TestFileProvider fileProvider = null,
            Action <RoslynCompilationContext> compilationCallback = null,
            RazorReferenceManager referenceManager          = null,
            IList <CompiledViewDescriptor> precompiledViews = null,
            CSharpCompiler csharpCompiler = null)
        {
            fileProvider = fileProvider ?? new TestFileProvider();
            var accessor = Mock.Of <IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);

            compilationCallback = compilationCallback ?? (_ => { });
            var options = Options.Create(new RazorViewEngineOptions());

            if (referenceManager == null)
            {
                referenceManager = CreateReferenceManager(options);
            }

            precompiledViews = precompiledViews ?? Array.Empty <CompiledViewDescriptor>();

            var hostingEnvironment = Mock.Of <IHostingEnvironment>(e => e.ContentRootPath == "BasePath");
            var fileSystem         = new FileProviderRazorProjectFileSystem(accessor, hostingEnvironment);
            var projectEngine      = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
            {
                RazorExtensions.Register(builder);
            });

            csharpCompiler = csharpCompiler ?? new CSharpCompiler(referenceManager, hostingEnvironment);

            var viewCompiler = new TestRazorViewCompiler(
                fileProvider,
                projectEngine,
                csharpCompiler,
                compilationCallback,
                precompiledViews);

            return(viewCompiler);
        }
Example #35
0
        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);
        }
Example #36
0
        public async Task CompileAsync_AddsChangeTokensForViewStartsIfFileExists_WhenWatchingForFileChanges()
        {
            // Arrange
            var path         = "/file/exists/FilePath.cshtml";
            var fileProvider = new TestFileProvider();

            fileProvider.AddFile(path, "Content");
            var viewCompiler = GetViewCompiler(fileProvider);

            viewCompiler.AllowRecompilingViewsOnFileChange = true;

            // 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("/_ViewImports.cshtml"), token),
                token => Assert.Same(fileProvider.GetChangeToken("/file/_ViewImports.cshtml"), token),
                token => Assert.Same(fileProvider.GetChangeToken("/file/exists/_ViewImports.cshtml"), token));
        }
        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);
        }
Example #38
0
        private IFileProvider GetFileProvider()
        {
            TestFileProvider fileProvider = new TestFileProvider();

            fileProvider.AddDirectory("/a");
            fileProvider.AddDirectory("/a/b");
            fileProvider.AddDirectory("/a/b/c");
            fileProvider.AddDirectory("/a/b/c/1");
            fileProvider.AddDirectory("/a/b/d");
            fileProvider.AddDirectory("/a/x");
            fileProvider.AddDirectory("/a/y");
            fileProvider.AddDirectory("/a/y/z");

            fileProvider.AddFile("/a/b/c/foo.txt");
            fileProvider.AddFile("/a/b/c/baz.txt");
            fileProvider.AddFile("/a/b/c/1/2.txt");
            fileProvider.AddFile("/a/b/d/baz.txt");
            fileProvider.AddFile("/a/x/bar.txt");
            fileProvider.AddFile("/a/x/foo.xml");
            fileProvider.AddFile("/a/x/foo.doc");

            return(fileProvider);
        }
Example #39
0
        public void GetItem_ReturnsFileFromDisk()
        {
            var fileProvider = new TestFileProvider("BasePath");
            var file1        = fileProvider.AddFile("File1.cshtml", "content");
            var file2        = fileProvider.AddFile("File2.js", "content");
            var file3        = fileProvider.AddFile("File3.cshtml", "content");

            fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });

            var accessor = Mock.Of <IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);

            var razorProject = new FileProviderRazorProject(accessor, Mock.Of <IHostingEnvironment>(e => e.ContentRootPath == "BasePath"));

            // Act
            var item = razorProject.GetItem("/File3.cshtml");

            // Assert
            Assert.True(item.Exists);
            Assert.Equal("/File3.cshtml", item.FilePath);
            Assert.Equal(string.Empty, item.BasePath);
            Assert.Equal(Path.Combine("BasePath", "File3.cshtml"), item.PhysicalPath);
            Assert.Equal("File3.cshtml", item.RelativePhysicalPath);
        }
Example #40
0
            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);
        }
Example #42
0
    public void SameConfigWhenReloadOnChangeIsFalse()
    {
        var testFileProvider = new TestFileProvider(
            new TestFile("Secret1", "SecretValue1"),
            new TestFile("Secret2", "SecretValue2"));

        var config = new ConfigurationBuilder()
                     .AddKeyPerFile(o =>
        {
            o.FileProvider   = testFileProvider;
            o.ReloadOnChange = false;
        }).Build();

        Assert.Equal("SecretValue1", config["Secret1"]);
        Assert.Equal("SecretValue2", config["Secret2"]);

        testFileProvider.ChangeFiles(
            new TestFile("Secret1", "NewSecretValue1"),
            new TestFile("Secret3", "NewSecretValue3"));

        Assert.Equal("SecretValue1", config["Secret1"]);
        Assert.Equal("SecretValue2", config["Secret2"]);
    }
        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 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);
        }
Example #45
0
        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);
            }
        }
Example #46
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 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);
        }
Example #47
0
        public void GetOrAdd_DoesNotRecompile_IfFileTriggerWasSetForViewImports(string globalImportPath)
        {
            // Arrange
            var fileProvider = new TestFileProvider();
            var cache = new CompilerCache(fileProvider, _precompiledViews);

            // Act
            fileProvider.Watch(globalImportPath);
            fileProvider.GetChangeToken(globalImportPath).HasChanged = true;
            var result = cache.GetOrAdd(PrecompiledViewsPath, ThrowsIfCalled);

            // Assert
            Assert.NotSame(CompilerCacheResult.FileNotFound, result);
            Assert.Same(typeof(PreCompile), result.CompilationResult.CompiledType);
        }
Example #48
0
        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 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 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);
            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_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 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 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 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 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 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 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);
                        });
                });
        }
Example #59
0
        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 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);
        }