Port old Razor tests to new Razor

This commit is contained in:
Ajay Bhargav Baaskaran 2017-02-02 13:23:03 -08:00
parent 8d5abd433f
commit c349929cc1
6 changed files with 250 additions and 403 deletions

View File

@ -33,7 +33,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
private const string CS0246 = nameof(CS0246);
private readonly CSharpCompiler _compiler;
private readonly IFileProvider _fileProvider;
private readonly ILogger _logger;
private readonly Action<RoslynCompilationContext> _compilationCallback;
@ -42,16 +41,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
/// </summary>
/// <param name="compiler">The <see cref="CSharpCompiler"/>.</param>
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public DefaultRoslynCompilationService(
CSharpCompiler compiler,
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
IOptions<RazorViewEngineOptions> optionsAccessor,
ILoggerFactory loggerFactory)
{
_compiler = compiler;
_fileProvider = fileProviderAccessor.FileProvider;
_compilationCallback = optionsAccessor.Value.CompilationCallback;
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
}

View File

@ -1,175 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Chunks;
using Microsoft.AspNetCore.Razor.Chunks.Generators;
using Microsoft.AspNetCore.Razor.CodeGenerators;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Microsoft.AspNetCore.Mvc.Razor.Host
{
public static class ChunkVisitorTestFactory
{
private static string _testClass = "TestClass";
private static string _testNamespace = "TestNamespace";
private static string _testFile = "TestFile";
public static CodeGeneratorContext CreateCodeGeneratorContext()
{
var language = new CSharpRazorCodeLanguage();
var host = new RazorEngineHost(language);
var chunkGeneratorContext = new ChunkGeneratorContext
(
host,
_testClass,
_testNamespace,
_testFile,
shouldGenerateLinePragmas: false
);
var codeGeneratorContext = new CodeGeneratorContext(
chunkGeneratorContext,
errorSink: new ErrorSink());
return codeGeneratorContext;
}
public static IList<Chunk> GetTestChunks(bool visitedTagHelperChunks)
{
return new List<Chunk>
{
GetTagHelperChunk("Baz"),
GetNestedViewComponentTagHelperChunk("Foo", visitedTagHelperChunks),
GetViewComponentTagHelperChunk("Bar", visitedTagHelperChunks),
GetIndexerViewComponentTagHelperChunk(
"Bee",
visitedTagHelperChunks,
"System.Collections.Generic.Dictionary<global::System.String, global::System.Collections.Generic.List<global::System.Int32>>"),
};
}
private static TagHelperChunk GetTagHelperChunk(string name)
{
var tagHelperChunk = new TagHelperChunk(
name.ToLowerInvariant(),
TagMode.SelfClosing,
new List<TagHelperAttributeTracker>(),
new List<TagHelperDescriptor>
{
new TagHelperDescriptor
{
AssemblyName = $"{name}Assembly",
TagName = name.ToLowerInvariant(),
TypeName = $"{name}Type",
}
});
return tagHelperChunk;
}
private static ParentChunk GetNestedViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks)
{
var parentChunk = GetTagHelperChunk("blah");
var tagHelperChunk = GetViewComponentTagHelperChunk(name, visitedTagHelperChunks);
parentChunk.Children.Add(tagHelperChunk);
return parentChunk;
}
private static TagHelperChunk GetViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks)
{
var typeName = visitedTagHelperChunks ? $"{_testNamespace}.{_testClass}.{name}Type" : $"{name}Type";
var attribute = new TagHelperAttributeDescriptor
{
Name = "attribute",
PropertyName = "Attribute",
TypeName = typeof(string).FullName
};
var requiredAttribute = new TagHelperRequiredAttributeDescriptor
{
Name = "Attribute"
};
var tagHelperDescriptor = new TagHelperDescriptor
{
AssemblyName = $"{name}Assembly",
TagName = name.ToLowerInvariant(),
TypeName = typeName,
Attributes = new[]
{
attribute
},
RequiredAttributes = new[]
{
requiredAttribute
}
};
tagHelperDescriptor.PropertyBag.Add(
ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey,
name);
var tagHelperChunk = new TagHelperChunk(
$"vc:{name.ToLowerInvariant()}",
TagMode.SelfClosing,
new List<TagHelperAttributeTracker>(),
new[]
{
tagHelperDescriptor
});
return tagHelperChunk;
}
private static TagHelperChunk GetIndexerViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks, string attributeTypeName)
{
var typeName = visitedTagHelperChunks ? $"{_testNamespace}.{_testClass}.{name}Type" : $"{name}Type";
var attribute = new TagHelperAttributeDescriptor
{
Name = "attribute",
PropertyName = "Attribute",
TypeName = attributeTypeName
};
var indexerAttribute = new TagHelperAttributeDescriptor
{
Name = attribute.Name + "-",
PropertyName = attribute.PropertyName,
TypeName = attributeTypeName,
IsIndexer = true
};
var tagHelperDescriptor = new TagHelperDescriptor
{
AssemblyName = $"{name}Assembly",
TagName = name.ToLowerInvariant(),
TypeName = typeName,
Attributes = new[]
{
attribute,
indexerAttribute
}
};
tagHelperDescriptor.PropertyBag.Add(
ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey,
name);
var tagHelperChunk = new TagHelperChunk(
$"vc:{name.ToLowerInvariant()}",
TagMode.SelfClosing,
new List<TagHelperAttributeTracker>(),
new[]
{
tagHelperDescriptor
});
return tagHelperChunk;
}
}
}

View File

@ -1,68 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Chunks;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Host.Test
{
public class TagHelperChunkDecoratorTest
{
#if OLD_RAZOR
[Fact]
public void Accept_CorrectlyDecoratesViewComponentChunks()
{
// Arrange
var codeGeneratorContext = ChunkVisitorTestFactory.CreateCodeGeneratorContext();
var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
foreach (var chunk in ChunkVisitorTestFactory.GetTestChunks(visitedTagHelperChunks: false))
{
codeGeneratorContext.ChunkTreeBuilder.AddChunk(chunk, syntaxTreeNode.Object);
}
var tagHelperChunkDecorator = new TagHelperChunkDecorator(codeGeneratorContext);
var expectedChunks = ChunkVisitorTestFactory.GetTestChunks(visitedTagHelperChunks: true);
// Act
var resultChunks = codeGeneratorContext.ChunkTreeBuilder.Root.Children;
tagHelperChunkDecorator.Accept(resultChunks);
// Assert
// Test the normal tag helper chunk, Baz.
Assert.Equal(expectedChunks.Count, resultChunks.Count);
var expectedTagHelperChunk = (TagHelperChunk)expectedChunks[0];
var resultTagHelperChunk = Assert.IsType<TagHelperChunk>(resultChunks[0]);
Assert.Equal(
expectedTagHelperChunk.Descriptors.First().TypeName,
Assert.Single(resultTagHelperChunk.Descriptors).TypeName);
// Test the parent chunk with view component tag helper inside, Foo.
var expectedParentChunk = (ParentChunk)expectedChunks[1];
var resultParentChunk = Assert.IsType<TagHelperChunk>(resultChunks[1]);
Assert.Single(resultParentChunk.Children);
expectedTagHelperChunk = (TagHelperChunk)expectedParentChunk.Children.First();
resultTagHelperChunk = (TagHelperChunk)resultParentChunk.Children.First();
Assert.Equal(expectedTagHelperChunk.Descriptors.First().TypeName,
resultTagHelperChunk.Descriptors.First().TypeName,
StringComparer.Ordinal);
// Test the view component tag helper, Bar.
expectedTagHelperChunk = expectedChunks.ElementAt(2) as TagHelperChunk;
resultTagHelperChunk = resultChunks.ElementAt(2) as TagHelperChunk;
Assert.NotNull(resultTagHelperChunk);
Assert.Equal(expectedTagHelperChunk.Descriptors.First().TypeName,
resultTagHelperChunk.Descriptors.First().TypeName,
StringComparer.Ordinal);
}
#endif
}
}

View File

@ -3,9 +3,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
@ -38,7 +36,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
TypeName = "System.Int32",
Name = "Foo",
}
}
}
};
@ -86,7 +83,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
Name = "Foo",
PropertyName = "Foo",
}
}
}
};
@ -169,7 +165,6 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.
PropertyName = "Tags",
IsIndexer = true,
}
}
}
};
@ -221,6 +216,99 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.
", vcthClass.Content);
}
[Fact]
public void ViewComponentTagHelperPass_Execute_CreatesViewComponentTagHelper_Nested()
{
// Arrange
var codeDocument = CreateDocument(@"
@addTagHelper *, TestAssembly
<p foo=""17""><tagcloud foo=""17""></p>");
var tagHelpers = new[]
{
new TagHelperDescriptor()
{
AssemblyName = "TestAssembly",
TypeName = "PTestTagHelper",
TagName = "p",
Attributes = new TagHelperAttributeDescriptor[]
{
new TagHelperAttributeDescriptor()
{
TypeName = "System.Int32",
Name = "Foo",
}
}
},
new TagHelperDescriptor()
{
AssemblyName = "TestAssembly",
TypeName = "TestTagHelper",
TagName = "tagcloud",
Attributes = new TagHelperAttributeDescriptor[]
{
new TagHelperAttributeDescriptor()
{
TypeName = "System.Int32",
Name = "Foo",
PropertyName = "Foo",
}
}
}
};
tagHelpers[1].PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "TagCloud");
var engine = CreateEngine(tagHelpers);
var pass = new ViewComponentTagHelperPass()
{
Engine = engine,
};
var irDocument = CreateIRDocument(engine, codeDocument);
var expectedTagHelperName = "PTestTagHelper";
var expectedVCTHName = "AspNetCore.Generated_test.__Generated__TagCloudViewComponentTagHelper";
// Act
pass.Execute(codeDocument, irDocument);
// Assert
var outerTagHelper = FindTagHelperNode(irDocument);
Assert.Equal(expectedTagHelperName, Assert.IsType<CreateTagHelperIRNode>(outerTagHelper.Children[1]).TagHelperTypeName);
Assert.Equal(expectedTagHelperName, Assert.IsType<SetTagHelperPropertyIRNode>(outerTagHelper.Children[2]).TagHelperTypeName);
var vcth = FindTagHelperNode(outerTagHelper.Children[0]);
Assert.Equal(expectedVCTHName, Assert.IsType<CreateTagHelperIRNode>(vcth.Children[1]).TagHelperTypeName);
Assert.Equal(expectedVCTHName, Assert.IsType<SetTagHelperPropertyIRNode>(vcth.Children[2]).TagHelperTypeName);
var @class = FindClassNode(irDocument);
Assert.Equal(3, @class.Children.Count);
var vcthClass = Assert.IsType<CSharpStatementIRNode>(@class.Children[2]);
Assert.Equal(@"[Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(""tagcloud"")]
public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper _helper = null;
public __Generated__TagCloudViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper)
{
_helper = helper;
}
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute]
public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
public System.Int32 Foo { get; set; }
public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output)
{
(_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext);
var content = await _helper.InvokeAsync(""TagCloud"", new { Foo });
output.TagName = null;
output.Content.SetHtmlContent(content);
}
}
", vcthClass.Content);
}
private RazorCodeDocument CreateDocument(string content)
{
using (var stream = new MemoryStream())

View File

@ -2,12 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options;
using Moq;
@ -17,7 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
public class DefaultRoslynCompilationServiceTest
{
#if OLD_RAZOR
[Fact]
public void Compile_ReturnsCompilationResult()
{
@ -26,12 +27,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
public class MyTestType {}";
var compilationService = GetRoslynCompilationService();
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path");
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "test.cshtml"));
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
// Assert
Assert.Equal("MyTestType", result.CompiledType.Name);
@ -46,20 +51,23 @@ public class MyTestType {}";
var content = $@"
#line 1 ""{viewPath}""
this should fail";
var fileProvider = new TestFileProvider();
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
var compilationService = GetRoslynCompilationService();
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(fileContent), viewPath));
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
// Assert
Assert.IsType<CompilationResult>(result);
Assert.Null(result.CompiledType);
var compilationFailure = Assert.Single(result.CompilationFailures);
Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath);
Assert.Equal(viewPath, compilationFailure.SourceFilePath);
Assert.Equal(fileContent, compilationFailure.SourceFileContent);
}
@ -67,16 +75,20 @@ this should fail";
public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
{
// Arrange
var viewPath = "some-relative-path";
var fileContent = "file content";
var content = "this should fail";
var compilationService = GetRoslynCompilationService();
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { Content = fileContent },
"some-relative-path");
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(fileContent), viewPath));
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
// Assert
Assert.IsType<CompilationResult>(result);
@ -87,39 +99,11 @@ this should fail";
Assert.Equal(content, compilationFailure.SourceFileContent);
}
[Fact]
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 = GetRoslynCompilationService(fileProvider: 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);
}
[Fact]
public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
{
// Arrange
var viewPath = "some-relative-path";
var content = @"
#if MY_CUSTOM_DEFINE
public class MyCustomDefinedClass {}
@ -130,12 +114,15 @@ public class MyNonCustomDefinedClass {}
var options = GetOptions();
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
var compilationService = GetRoslynCompilationService(options: options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path");
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), viewPath));
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
// Assert
Assert.NotNull(result.CompiledType);
@ -148,11 +135,8 @@ public class MyNonCustomDefinedClass {}
// 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 = GetRoslynCompilationService(options: options, fileProvider: fileProvider);
var compilationService = GetRoslynCompilationService();
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent("view-content"), viewPath));
var assemblyName = "random-assembly-name";
var diagnostics = new[]
@ -179,7 +163,7 @@ public class MyNonCustomDefinedClass {}
// Act
var compilationResult = compilationService.GetCompilationFailedResult(
viewPath,
codeDocument,
"compilation-content",
assemblyName,
diagnostics);
@ -235,13 +219,16 @@ public class MyNonCustomDefinedClass {}
RoslynCompilationContext usedCompilation = null;
var options = GetOptions(c => usedCompilation = c);
var compilationService = GetRoslynCompilationService(options: options);
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path"));
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path");
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
Assert.NotNull(usedCompilation);
Assert.Single(usedCompilation.Compilation.SyntaxTrees);
@ -257,12 +244,15 @@ public class MyNonCustomDefinedClass {}
});
var content = "public class MyTestType {}";
var compilationService = GetRoslynCompilationService(options: options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path.cshtml");
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path.cshtml"));
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
// Assert
Assert.Single(result.CompilationFailures);
@ -284,12 +274,15 @@ public class MyNonCustomDefinedClass {}
var applicationPartManager = new ApplicationPartManager();
var compilationService = GetRoslynCompilationService(applicationPartManager, options);
var relativeFileInfo = new RelativeFileInfo(
new TestFileInfo { PhysicalPath = "SomePath" },
"some-relative-path.cshtml");
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path.cshtml"));
var csharpDocument = new RazorCSharpDocument()
{
GeneratedCode = content
};
// Act
var result = compilationService.Compile(relativeFileInfo, content);
var result = compilationService.Compile(codeDocument, csharpDocument);
// Assert
Assert.Null(result.CompilationFailures);
@ -315,15 +308,6 @@ public class MyNonCustomDefinedClass {}
};
}
private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
{
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
options.SetupGet(o => o.FileProvider)
.Returns(fileProvider ?? new TestFileProvider());
return options.Object;
}
private static IOptions<RazorViewEngineOptions> GetAccessor(RazorViewEngineOptions options)
{
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
@ -343,8 +327,7 @@ public class MyNonCustomDefinedClass {}
private static DefaultRoslynCompilationService GetRoslynCompilationService(
ApplicationPartManager partManager = null,
RazorViewEngineOptions options = null,
IFileProvider fileProvider = null)
RazorViewEngineOptions options = null)
{
partManager = partManager ?? GetApplicationPartManager();
options = options ?? GetOptions();
@ -354,10 +337,22 @@ public class MyNonCustomDefinedClass {}
return new DefaultRoslynCompilationService(
compiler,
GetFileProviderAccessor(fileProvider),
optionsAccessor,
NullLoggerFactory.Instance);
}
#endif
private static MemoryStream CreateStreamContent(string content = "Hello, World!", Encoding encoding = null)
{
var stream = new MemoryStream();
encoding = encoding ?? Encoding.UTF8;
using (var writer = new StreamWriter(stream, encoding, bufferSize: 1024, leaveOpen: true))
{
writer.Write(content);
}
stream.Seek(0L, SeekOrigin.Begin);
return stream;
}
}
}

View File

@ -1,17 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Chunks;
using Microsoft.AspNetCore.Razor.CodeGenerators;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
@ -19,61 +15,82 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
public class RazorCompilationServiceTest
{
#if OLD_RAZOR
[Theory]
[InlineData(@"src\work\myapp", @"src\work\myapp\Views\index\home.cshtml")]
[InlineData(@"src\work\myapp\", @"src\work\myapp\Views\index\home.cshtml")]
public void CompileCalculatesRootRelativePath(string appPath, string viewPath)
[Fact]
public void CompileCalculatesRootRelativePath()
{
// Arrange
var host = new Mock<RazorEngineHost>();
host.Setup(h => h.GenerateCode(@"Views\index\home.cshtml", It.IsAny<Stream>()))
.Returns(GetGeneratorResult())
.Verifiable();
var viewPath = @"src\work\myapp\Views\index\home.cshtml";
var relativePath = @"Views\index\home.cshtml";
var fileInfo = new Mock<IFileInfo>();
fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath);
fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null);
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 }));
var fileProvider = new TestFileProvider();
fileProvider.AddFile(relativePath, fileInfo.Object);
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath);
var compiler = new Mock<ICompilationService>();
compiler.Setup(c => c.Compile(relativeFileInfo, It.IsAny<string>()))
compiler.Setup(c => c.Compile(It.IsAny<RazorCodeDocument>(), It.IsAny<RazorCSharpDocument>()))
.Returns(new CompilationResult(typeof(RazorCompilationServiceTest)));
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);
var engine = new Mock<RazorEngine>();
engine.Setup(e => e.Process(It.IsAny<RazorCodeDocument>()))
.Callback<RazorCodeDocument>(document =>
{
document.SetCSharpDocument(new RazorCSharpDocument()
{
Diagnostics = new List<RazorError>()
});
Assert.Equal(viewPath, document.Source.Filename); // Assert if source file name is the root relative path
}).Verifiable();
var razorService = new RazorCompilationService(
compiler.Object,
engine.Object,
new DefaultRazorProject(fileProvider),
GetFileProviderAccessor(fileProvider),
NullLoggerFactory.Instance);
// Act
razorService.Compile(relativeFileInfo);
// Assert
host.Verify();
engine.Verify();
}
[Fact]
public void Compile_ReturnsFailedResultIfParseFails()
{
// Arrange
var errorSink = new ErrorSink();
errorSink.OnError(new RazorError("some message", 1, 1, 1, 1));
var generatorResult = new GeneratorResults(
new Block(new BlockBuilder { Type = BlockType.Comment }),
Enumerable.Empty<TagHelperDescriptor>(),
errorSink,
new CodeGeneratorResult("", new LineMapping[0]),
new ChunkTree());
var host = new Mock<IMvcRazorHost>();
host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
.Returns(generatorResult)
.Verifiable();
var relativePath = @"Views\index\home.cshtml";
var fileInfo = new Mock<IFileInfo>();
fileInfo.Setup(f => f.CreateReadStream())
.Returns(Stream.Null);
fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 }));
var fileProvider = new TestFileProvider();
fileProvider.AddFile(relativePath, fileInfo.Object);
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath);
var compiler = new Mock<ICompilationService>(MockBehavior.Strict);
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);
var engine = new Mock<RazorEngine>();
engine.Setup(e => e.Process(It.IsAny<RazorCodeDocument>()))
.Callback<RazorCodeDocument>(document =>
{
document.SetCSharpDocument(new RazorCSharpDocument()
{
Diagnostics = new List<RazorError>()
{
new RazorError("some message", 1, 1, 1, 1)
}
});
}).Verifiable();
var razorService = new RazorCompilationService(
compiler.Object,
engine.Object,
new DefaultRazorProject(fileProvider),
GetFileProviderAccessor(fileProvider),
NullLoggerFactory.Instance);
// Act
var result = razorService.Compile(relativeFileInfo);
@ -86,35 +103,41 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var message = Assert.Single(failure.Messages);
Assert.Equal("some message", message.Message);
});
host.Verify();
engine.Verify();
}
[Fact]
public void Compile_ReturnsResultFromCompilationServiceIfParseSucceeds()
{
// Arrange
var code = "compiled-content";
var generatorResult = new GeneratorResults(
new Block(new BlockBuilder { Type = BlockType.Comment }),
Enumerable.Empty<TagHelperDescriptor>(),
new ErrorSink(),
new CodeGeneratorResult(code, new LineMapping[0]),
new ChunkTree());
var host = new Mock<IMvcRazorHost>();
host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
.Returns(generatorResult);
var relativePath = @"Views\index\home.cshtml";
var fileInfo = new Mock<IFileInfo>();
fileInfo.Setup(f => f.CreateReadStream())
.Returns(Stream.Null);
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 }));
var fileProvider = new TestFileProvider();
fileProvider.AddFile(relativePath, fileInfo.Object);
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath);
var compilationResult = new CompilationResult(typeof(object));
var compiler = new Mock<ICompilationService>();
compiler.Setup(c => c.Compile(relativeFileInfo, code))
compiler.Setup(c => c.Compile(It.IsAny<RazorCodeDocument>(), It.IsAny<RazorCSharpDocument>()))
.Returns(compilationResult)
.Verifiable();
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);
var engine = new Mock<RazorEngine>();
engine.Setup(e => e.Process(It.IsAny<RazorCodeDocument>()))
.Callback<RazorCodeDocument>(document =>
{
document.SetCSharpDocument(new RazorCSharpDocument()
{
Diagnostics = new List<RazorError>()
});
});
var razorService = new RazorCompilationService(
compiler.Object,
engine.Object,
new DefaultRazorProject(fileProvider),
GetFileProviderAccessor(fileProvider),
NullLoggerFactory.Instance);
// Act
var result = razorService.Compile(relativeFileInfo);
@ -130,7 +153,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
// 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");
@ -138,7 +160,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
var relativeFileInfo = new RelativeFileInfo(file, viewPath);
var razorService = new RazorCompilationService(
Mock.Of<ICompilationService>(),
Mock.Of<IMvcRazorHost>(),
Mock.Of<RazorEngine>(),
new DefaultRazorProject(fileProvider),
GetFileProviderAccessor(fileProvider),
NullLoggerFactory.Instance);
var errors = new[]
@ -205,16 +228,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
});
}
private static GeneratorResults GetGeneratorResult()
{
return new GeneratorResults(
new Block(new BlockBuilder { Type = BlockType.Comment }),
Enumerable.Empty<TagHelperDescriptor>(),
new ErrorSink(),
new CodeGeneratorResult("", new LineMapping[0]),
new ChunkTree());
}
private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
{
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
@ -223,7 +236,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
return options.Object;
}
#endif
}
}