示例#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 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);
        }
示例#2
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(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);
        }
示例#3
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);
        }
示例#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(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());
        }
示例#5
0
        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);
        }
示例#6
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     = 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);
        }
示例#7
0
        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);
        }
示例#8
0
        /// <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));
                }
            }
        }