示例#1
0
        public void GetOrAdd_ReturnsNewResultIfFileWasModified()
        {
            // Arrange
            var fileProvider = new TestFileProvider();

            fileProvider.AddFile(ViewPath, "some content");
            var cache     = new CompilerCache(Enumerable.Empty <RazorFileInfoCollection>(), TestLoadContext, 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.GetTrigger(ViewPath).IsExpired = true;
            var result3 = cache.GetOrAdd(ViewPath, _ => expected2);

            // Assert 3
            Assert.NotSame(CompilerCacheResult.FileNotFound, result3);
            Assert.Same(expected2, result3.CompilationResult);
        }
示例#2
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);
        }
示例#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);
        }
示例#4
0
        public void GetOrAdd_DoesNotQueryFileSystem_IfCachedFileTriggerWasNotSet()
        {
            // Arrange
            var mockFileProvider = new Mock <TestFileProvider> {
                CallBase = true
            };
            var fileProvider = mockFileProvider.Object;

            fileProvider.AddFile(ViewPath, "some content");
            var cache    = new CompilerCache(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
            var result2 = cache.GetOrAdd(ViewPath, ThrowsIfCalled);

            // Assert 2
            Assert.NotSame(CompilerCacheResult.FileNotFound, result2);
            Assert.IsType <CompilationResult>(result2.CompilationResult);
            Assert.Same(type, result2.CompilationResult.CompiledType);
            mockFileProvider.Verify(v => v.GetFileInfo(ViewPath), Times.Once());
        }
示例#5
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);
        }
示例#6
0
        public void GetOrAdd_ReturnsNewResult_IfAncestorViewImportsWereModified(string globalImportPath)
        {
            // Arrange
            var fileProvider = new TestFileProvider();

            fileProvider.AddFile(ViewPath, "some content");
            var cache     = new CompilerCache(fileProvider);
            var expected1 = 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);
        }
示例#7
0
        public void GetOrAdd_ReturnsNewResultIfFileWasModified()
        {
            // Arrange
            var fileProvider = new TestFileProvider();

            fileProvider.AddFile(ViewPath, "some content");
            var cache     = new CompilerCache(Enumerable.Empty <RazorFileInfoCollection>(), TestLoadContext, fileProvider);
            var type      = typeof(RuntimeCompileIdentical);
            var expected1 = UncachedCompilationResult.Successful(type, "hello world");
            var expected2 = UncachedCompilationResult.Successful(type, "different content");

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

            // Assert 1
            Assert.NotSame(CompilerCacheResult.FileNotFound, result1);
            Assert.Same(expected1, result1.CompilationResult);

            // Act 2
            fileProvider.GetTrigger(ViewPath).IsExpired = true;
            var result2 = cache.GetOrAdd(ViewPath, _ => expected2);

            // Assert 2
            Assert.NotSame(CompilerCacheResult.FileNotFound, result2);
            Assert.Same(expected2, result2.CompilationResult);
        }
示例#8
0
        public void GetOrAdd_DoesNotCacheCompiledContent_OnCallsAfterInitial()
        {
            // Arrange
            var lastModified = DateTime.UtcNow;
            var fileProvider = new TestFileProvider();
            var cache        = new CompilerCache(Enumerable.Empty <RazorFileInfoCollection>(), TestLoadContext, fileProvider);
            var fileInfo     = new TestFileInfo
            {
                PhysicalPath = "test",
                LastModified = lastModified
            };

            fileProvider.AddFile("test", fileInfo);
            var type           = GetType();
            var uncachedResult = UncachedCompilationResult.Successful(type, "hello world");

            // Act
            cache.GetOrAdd("test", _ => uncachedResult);
            var result1 = cache.GetOrAdd("test", _ => { throw new Exception("shouldn't be called."); });
            var result2 = cache.GetOrAdd("test", _ => { throw new Exception("shouldn't be called."); });

            // Assert
            Assert.NotSame(CompilerCacheResult.FileNotFound, result1);
            Assert.NotSame(CompilerCacheResult.FileNotFound, result2);

            var actual1 = Assert.IsType <CompilationResult>(result1.CompilationResult);
            var actual2 = Assert.IsType <CompilationResult>(result2.CompilationResult);

            Assert.NotSame(uncachedResult, actual1);
            Assert.NotSame(uncachedResult, actual2);
            Assert.Same(type, actual1.CompiledType);
            Assert.Same(type, actual2.CompiledType);
        }
示例#9
0
        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);
        }
示例#10
0
        /// <inheritdoc />
        public CompilationResult Compile(IFileInfo fileInfo, string compilationContent)
        {
            var sourceText  = SourceText.From(compilationContent, Encoding.UTF8);
            var syntaxTrees = new[] { CSharpSyntaxTree.ParseText(sourceText, path: fileInfo.PhysicalPath) };

            var references = _applicationReferences.Value;

            var assemblyName = Path.GetRandomFileName();

            var compilation = CSharpCompilation.Create(assemblyName,
                                                       options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
                                                       syntaxTrees: syntaxTrees,
                                                       references: references);

            using (var ms = new MemoryStream())
            {
                using (var pdb = new MemoryStream())
                {
                    EmitResult result;

                    if (PlatformHelper.IsMono)
                    {
                        result = compilation.Emit(ms, pdbStream: null);
                    }
                    else
                    {
                        result = compilation.Emit(ms, pdbStream: pdb);
                    }

                    if (!result.Success)
                    {
                        var formatter = new DiagnosticFormatter();

                        var messages = result.Diagnostics
                                       .Where(IsError)
                                       .Select(d => GetCompilationMessage(formatter, d))
                                       .ToList();

                        return(CompilationResult.Failed(fileInfo, compilationContent, messages));
                    }

                    Assembly assembly;
                    ms.Seek(0, SeekOrigin.Begin);

                    if (PlatformHelper.IsMono)
                    {
                        assembly = _loader.LoadStream(ms, pdbStream: null);
                    }
                    else
                    {
                        pdb.Seek(0, SeekOrigin.Begin);
                        assembly = _loader.LoadStream(ms, pdb);
                    }

                    var type = assembly.GetExportedTypes()
                               .First();

                    return(UncachedCompilationResult.Successful(type, compilationContent));
                }
            }
        }
        /// <inheritdoc />
        public CompilationResult Compile([NotNull] RelativeFileInfo fileInfo, [NotNull] string compilationContent)
        {
            var assemblyName        = Path.GetRandomFileName();
            var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
            var syntaxTree          = SyntaxTreeGenerator.Generate(compilationContent,
                                                                   assemblyName,
                                                                   compilationSettings);
            var references = _applicationReferences.Value;

            var compilationOptions = compilationSettings.CompilationOptions
                                     .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            var compilation = CSharpCompilation.Create(assemblyName,
                                                       options: compilationOptions,
                                                       syntaxTrees: new[] { syntaxTree },
                                                       references: references);

            using (var ms = new MemoryStream())
            {
                using (var pdb = new MemoryStream())
                {
                    EmitResult result;

                    if (_supportsPdbGeneration.Value)
                    {
                        result = compilation.Emit(ms, pdbStream: pdb);
                    }
                    else
                    {
                        result = compilation.Emit(ms);
                    }

                    if (!result.Success)
                    {
                        return(GetCompilationFailedResult(
                                   fileInfo.RelativePath,
                                   compilationContent,
                                   assemblyName,
                                   result.Diagnostics));
                    }

                    Assembly assembly;
                    ms.Seek(0, SeekOrigin.Begin);

                    if (_supportsPdbGeneration.Value)
                    {
                        pdb.Seek(0, SeekOrigin.Begin);
                        assembly = _loader.LoadStream(ms, pdb);
                    }
                    else
                    {
                        assembly = _loader.LoadStream(ms, assemblySymbols: null);
                    }

                    var type = assembly.GetExportedTypes()
                               .First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));

                    return(UncachedCompilationResult.Successful(type, compilationContent));
                }
            }
        }
示例#12
0
        /// <inheritdoc />
        public CompilationResult Compile(IFileInfo fileInfo, string compilationContent)
        {
            var syntaxTrees = new[] { SyntaxTreeGenerator.Generate(compilationContent, fileInfo.PhysicalPath) };

            var references = _applicationReferences.Value;

            var assemblyName = Path.GetRandomFileName();

            var compilation = CSharpCompilation.Create(assemblyName,
                                                       options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
                                                       syntaxTrees: syntaxTrees,
                                                       references: references);

            using (var ms = new MemoryStream())
            {
                using (var pdb = new MemoryStream())
                {
                    EmitResult result;

                    if (_supportsPdbGeneration.Value)
                    {
                        result = compilation.Emit(ms, pdbStream: pdb);
                    }
                    else
                    {
                        result = compilation.Emit(ms);
                    }

                    if (!result.Success)
                    {
                        var formatter = new DiagnosticFormatter();

                        var messages = result.Diagnostics
                                       .Where(IsError)
                                       .Select(d => GetCompilationMessage(formatter, d))
                                       .ToList();

                        return(CompilationResult.Failed(fileInfo, compilationContent, messages));
                    }

                    Assembly assembly;
                    ms.Seek(0, SeekOrigin.Begin);

                    if (_supportsPdbGeneration.Value)
                    {
                        pdb.Seek(0, SeekOrigin.Begin);
                        assembly = _loader.LoadStream(ms, pdb);
                    }
                    else
                    {
                        assembly = _loader.LoadStream(ms, assemblySymbols: null);
                    }

                    var type = assembly.GetExportedTypes()
                               .First(t => t.Name.
                                      StartsWith(_classPrefix, StringComparison.Ordinal));

                    return(UncachedCompilationResult.Successful(type));
                }
            }
        }