Some cleanup around FileProviderRazorProject with tests

This commit is contained in:
Ajay Bhargav Baaskaran 2018-01-12 15:31:16 -08:00
parent 1d6b02c1f5
commit 2c6ba372c1
5 changed files with 99 additions and 41 deletions

View File

@ -37,15 +37,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
path = NormalizeAndEnsureValidPath(path);
var fileInfo = _provider.GetFileInfo(path);
string relativePhysicalPath = null;
if (fileInfo != null && fileInfo.Exists)
{
var absoluteBasePath = _hostingEnvironment.ContentRootPath;
relativePhysicalPath = fileInfo?.PhysicalPath?.Substring(absoluteBasePath.Length + 1); // Include leading separator
relativePhysicalPath = relativePhysicalPath ?? path; // Use the incoming path if the file is not directly accessible
}
return new FileProviderRazorProjectItem(fileInfo, basePath: string.Empty, filePath: path, relativePhysicalPath: relativePhysicalPath);
return new FileProviderRazorProjectItem(fileInfo, basePath: string.Empty, filePath: path, root: _hostingEnvironment.ContentRootPath);
}
public override IEnumerable<RazorProjectItem> EnumerateItems(string path)
@ -58,11 +50,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
if (directory.Exists)
{
foreach (var file in directory)
foreach (var fileInfo in directory)
{
if (file.IsDirectory)
if (fileInfo.IsDirectory)
{
var relativePath = prefix + "/" + file.Name;
var relativePath = prefix + "/" + fileInfo.Name;
var subDirectory = _provider.GetDirectoryContents(JoinPath(basePath, relativePath));
var children = EnumerateFiles(subDirectory, basePath, relativePath);
foreach (var child in children)
@ -70,14 +62,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
yield return child;
}
}
else if (string.Equals(RazorFileExtension, Path.GetExtension(file.Name), StringComparison.OrdinalIgnoreCase))
else if (string.Equals(RazorFileExtension, Path.GetExtension(fileInfo.Name), StringComparison.OrdinalIgnoreCase))
{
var filePath = prefix + "/" + file.Name;
var absoluteBasePath = _hostingEnvironment.ContentRootPath;
var relativePhysicalPath = file.PhysicalPath?.Substring(absoluteBasePath.Length + 1); // Include leading separator
relativePhysicalPath = relativePhysicalPath ?? filePath; // Use the incoming path if the file is not directly accessible
var filePath = prefix + "/" + fileInfo.Name;
yield return new FileProviderRazorProjectItem(file, basePath, filePath: filePath, relativePhysicalPath: relativePhysicalPath);
yield return new FileProviderRazorProjectItem(fileInfo, basePath, filePath: filePath, root: _hostingEnvironment.ContentRootPath);
}
}
}

View File

@ -1,6 +1,7 @@
// 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.IO;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.FileProviders;
@ -9,12 +10,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
public class FileProviderRazorProjectItem : RazorProjectItem
{
public FileProviderRazorProjectItem(IFileInfo fileInfo, string basePath, string filePath, string relativePhysicalPath)
private string _root;
private string _relativePhysicalPath;
private bool _isRelativePhysicalPathSet;
public FileProviderRazorProjectItem(IFileInfo fileInfo, string basePath, string filePath, string root)
{
FileInfo = fileInfo;
BasePath = basePath;
FilePath = filePath;
RelativePhysicalPath = relativePhysicalPath;
_root = root;
}
public IFileInfo FileInfo { get; }
@ -27,7 +32,30 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
public override string PhysicalPath => FileInfo.PhysicalPath;
public override string RelativePhysicalPath { get; }
public override string RelativePhysicalPath
{
get
{
if (!_isRelativePhysicalPathSet)
{
_isRelativePhysicalPathSet = true;
if (Exists)
{
if (_root != null &&
!string.IsNullOrEmpty(PhysicalPath) &&
PhysicalPath.StartsWith(_root, StringComparison.OrdinalIgnoreCase) &&
PhysicalPath.Length > _root.Length &&
(PhysicalPath[_root.Length] == Path.DirectorySeparatorChar || PhysicalPath[_root.Length] == Path.AltDirectorySeparatorChar))
{
_relativePhysicalPath = PhysicalPath.Substring(_root.Length + 1); // Include leading separator
}
}
}
return _relativePhysicalPath;
}
}
public override Stream Read()
{

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
// Assert
var failure = Assert.Single(compilationResult.CompilationFailures);
Assert.Equal(viewPath, failure.SourceFilePath);
Assert.Equal(Path.Combine("Views", "Home", "Index.cshtml"), failure.SourceFilePath);
Assert.Collection(failure.Messages,
message => Assert.StartsWith(
@"Unterminated string literal.",
@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
compilationResult.CompilationFailures,
failure =>
{
Assert.Equal(viewPath, failure.SourceFilePath);
Assert.Equal(Path.Combine("Views", "Home", "Index.cshtml"), failure.SourceFilePath);
Assert.Collection(failure.Messages,
message =>
{

View File

@ -17,8 +17,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
// Arrange
var fileProvider = new TestFileProvider("BasePath");
var file1 = fileProvider.AddFile("File1.txt", "content");
var file2 = fileProvider.AddFile("File2.js", "content");
var file1 = fileProvider.AddFile("/File1.txt", "content");
var file2 = fileProvider.AddFile("/File2.js", "content");
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2 });
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
@ -37,9 +37,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
// Arrange
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");
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);
@ -84,9 +84,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
};
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
var file2 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File2.cshtml"), "content");
var file3 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File3.cshtml"), "content");
var file4 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File4.txt"), "content");
var file2 = fileProvider.AddFile("/Level1-Dir1/File2.cshtml", "content");
var file3 = fileProvider.AddFile("/Level1-Dir1/File3.cshtml", "content");
var file4 = fileProvider.AddFile("/Level1-Dir1/File4.txt", "content");
var directory3 = new TestDirectoryFileInfo
{
Name = "Level2-Dir1"
@ -144,16 +144,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
Name = "Level1-Dir1",
};
var file1 = fileProvider.AddFile(Path.Combine("BasePath", "File1.cshtml"), "content");
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
var directory2 = new TestDirectoryFileInfo
{
Name = "Level1-Dir2",
};
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
var file2 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File2.cshtml"), "content");
var file3 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File3.cshtml"), "content");
var file4 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File4.txt"), "content");
var file2 = fileProvider.AddFile("/Level1-Dir1/File2.cshtml", "content");
var file3 = fileProvider.AddFile("/Level1-Dir1/File3.cshtml", "content");
var file4 = fileProvider.AddFile("/Level1-Dir1/File4.txt", "content");
var directory3 = new TestDirectoryFileInfo
{
Name = "Level2-Dir1"
@ -188,13 +188,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
});
}
[Fact(Skip = "Need to follow-up https://github.com/aspnet/Mvc/pull/7228")]
[Fact]
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");
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);
@ -212,12 +212,36 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
Assert.Equal("File3.cshtml", item.RelativePhysicalPath);
}
[Fact]
public void GetItem_PhysicalPathDoesNotStartWithContentRoot_ReturnsNull()
{
var fileProvider = new TestFileProvider("BasePath2");
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("BasePath2", "File3.cshtml"), item.PhysicalPath);
Assert.Null(item.RelativePhysicalPath);
}
[Fact]
public void GetItem_ReturnsNotFoundResult()
{
// Arrange
var fileProvider = new TestFileProvider("BasePath");
var file = fileProvider.AddFile("SomeFile.cshtml", "content");
var file = fileProvider.AddFile("/SomeFile.cshtml", "content");
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file });
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
var fileInfo = new TestFileInfo
{
Content = contents,
PhysicalPath = Path.Combine(Root, path),
PhysicalPath = Path.Combine(Root, NormalizeAndEnsureValidPhysicalPath(path)),
Name = Path.GetFileName(path),
LastModified = DateTime.UtcNow,
};
@ -109,6 +109,23 @@ namespace Microsoft.AspNetCore.Mvc.Razor
return _fileTriggers[filter];
}
private static string NormalizeAndEnsureValidPhysicalPath(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
return filePath;
}
filePath = filePath.Replace('/', Path.DirectorySeparatorChar);
if (filePath[0] == Path.DirectorySeparatorChar)
{
filePath = filePath.Substring(1);
}
return filePath;
}
private class NotFoundFileInfo : IFileInfo
{
public bool Exists