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); }
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(RuntimeCompileIdentical); 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, _ => { throw new Exception("shouldn't be called."); }); // Assert 2 Assert.Same(CompilerCacheResult.FileNotFound, result2); Assert.Null(result2.CompilationResult); }
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); }
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(RuntimeCompileIdentical); 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, _ => { throw new Exception("shouldn't be called"); }); // 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()); }
public void GetOrAdd_DoesNotCacheCompiledContent_OnCallsAfterInitial() { // Arrange var lastModified = DateTime.UtcNow; var cache = new CompilerCache(Enumerable.Empty <RazorFileInfoCollection>(), new TestFileProvider()); var fileInfo = new TestFileInfo { PhysicalPath = "test", LastModified = lastModified }; var type = GetType(); var uncachedResult = UncachedCompilationResult.Successful(type, "hello world"); var runtimeFileInfo = new RelativeFileInfo(fileInfo, "test"); // Act cache.GetOrAdd(runtimeFileInfo, _ => uncachedResult); var actual1 = cache.GetOrAdd(runtimeFileInfo, _ => uncachedResult); var actual2 = cache.GetOrAdd(runtimeFileInfo, _ => uncachedResult); // Assert Assert.NotSame(uncachedResult, actual1); Assert.NotSame(uncachedResult, actual2); var result = Assert.IsType <CompilationResult>(actual1); Assert.Null(actual1.CompiledContent); Assert.Same(type, actual1.CompiledType); result = Assert.IsType <CompilationResult>(actual2); Assert.Null(actual2.CompiledContent); Assert.Same(type, actual2.CompiledType); }
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 = GetType(); var expected = UncachedCompilationResult.Successful(type, "hello world"); // Act var result = cache.GetOrAdd(ViewPath, _ => expected); // Assert Assert.NotSame(CompilerCacheResult.FileNotFound, result); var actual = Assert.IsType <UncachedCompilationResult>(result.CompilationResult); Assert.NotNull(actual); Assert.Same(expected, actual); Assert.Equal("hello world", actual.CompiledContent); Assert.Same(type, actual.CompiledType); }
public void GetOrAdd_ReturnsCompilationResultFromFactory() { // Arrange var fileSystem = new TestFileSystem(); var cache = new CompilerCache(Enumerable.Empty <RazorFileInfoCollection>(), fileSystem); var fileInfo = new TestFileInfo { LastModified = DateTime.FromFileTimeUtc(10000) }; var type = GetType(); var expected = UncachedCompilationResult.Successful(type, "hello world"); var runtimeFileInfo = new RelativeFileInfo(fileInfo, "ab"); // Act var actual = cache.GetOrAdd(runtimeFileInfo, _ => expected); // Assert Assert.Same(expected, actual); Assert.Equal("hello world", actual.CompiledContent); Assert.Same(type, actual.CompiledType); }
/// <inheritdoc /> public CompilationResult Compile([NotNull] IFileInfo fileInfo, [NotNull] string compilationContent) { // The path passed to SyntaxTreeGenerator.Generate is used by the compiler to generate symbols (pdb) that // map to the source file. If a file does not exist on a physical file system, PhysicalPath will be null. // This prevents files that exist in a non-physical file system from being debugged. var path = fileInfo.PhysicalPath ?? fileInfo.Name; var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment); var syntaxTree = SyntaxTreeGenerator.Generate(compilationContent, path, compilationSettings); var references = _applicationReferences.Value; var assemblyName = Path.GetRandomFileName(); 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) { 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, compilationContent)); } } }