[Fixes #157] ErrorPage middleware doesn't show source code lines of Razor files
This commit is contained in:
parent
6e72a3935d
commit
8d583a4718
|
|
@ -11,6 +11,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Diagnostics.Views;
|
using Microsoft.AspNet.Diagnostics.Views;
|
||||||
|
using Microsoft.AspNet.FileProviders;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
|
@ -28,6 +29,7 @@ namespace Microsoft.AspNet.Diagnostics
|
||||||
private readonly ErrorPageOptions _options;
|
private readonly ErrorPageOptions _options;
|
||||||
private static readonly bool IsMono = Type.GetType("Mono.Runtime") != null;
|
private static readonly bool IsMono = Type.GetType("Mono.Runtime") != null;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly IFileProvider _fileProvider;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ErrorPageMiddleware"/> class
|
/// Initializes a new instance of the <see cref="ErrorPageMiddleware"/> class
|
||||||
|
|
@ -35,11 +37,15 @@ namespace Microsoft.AspNet.Diagnostics
|
||||||
/// <param name="next"></param>
|
/// <param name="next"></param>
|
||||||
/// <param name="options"></param>
|
/// <param name="options"></param>
|
||||||
public ErrorPageMiddleware(
|
public ErrorPageMiddleware(
|
||||||
[NotNull] RequestDelegate next, [NotNull] ErrorPageOptions options, ILoggerFactory loggerFactory)
|
[NotNull] RequestDelegate next,
|
||||||
|
[NotNull] ErrorPageOptions options,
|
||||||
|
ILoggerFactory loggerFactory,
|
||||||
|
IApplicationEnvironment appEnvironment)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_options = options;
|
_options = options;
|
||||||
_logger = loggerFactory.CreateLogger<ErrorPageMiddleware>();
|
_logger = loggerFactory.CreateLogger<ErrorPageMiddleware>();
|
||||||
|
_fileProvider = options.FileProvider ?? new PhysicalFileProvider(appEnvironment.ApplicationBasePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -183,31 +189,102 @@ namespace Microsoft.AspNet.Diagnostics
|
||||||
|
|
||||||
int lineNumber = line.ToInt32();
|
int lineNumber = line.ToInt32();
|
||||||
|
|
||||||
return string.IsNullOrEmpty(file)
|
if (string.IsNullOrEmpty(file))
|
||||||
? LoadFrame(string.IsNullOrEmpty(function) ? line.ToString() : function, string.Empty, 0)
|
{
|
||||||
: LoadFrame(function, file, lineNumber);
|
return GetStackFrame(
|
||||||
|
// Handle stack trace lines like
|
||||||
|
// "--- End of stack trace from previous location where exception from thrown ---"
|
||||||
|
string.IsNullOrEmpty(function) ? line.ToString() : function,
|
||||||
|
file: string.Empty,
|
||||||
|
lineNumber: 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return GetStackFrame(function, file, lineNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackFrame LoadFrame(string function, string file, int lineNumber)
|
// make it internal to enable unit testing
|
||||||
|
internal StackFrame GetStackFrame(string function, string file, int lineNumber)
|
||||||
{
|
{
|
||||||
var frame = new StackFrame { Function = function, File = file, Line = lineNumber };
|
var frame = new StackFrame { Function = function, File = file, Line = lineNumber };
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(file))
|
||||||
|
{
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> lines = null;
|
||||||
if (File.Exists(file))
|
if (File.Exists(file))
|
||||||
{
|
{
|
||||||
var code = File.ReadLines(file);
|
lines = File.ReadLines(file);
|
||||||
ReadFrameContent(frame, code, lineNumber, lineNumber);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Handle relative paths and embedded files
|
||||||
|
var fileInfo = _fileProvider.GetFileInfo(file);
|
||||||
|
if (fileInfo.Exists)
|
||||||
|
{
|
||||||
|
// ReadLines doesn't accept a stream. Use ReadLines as its more efficient
|
||||||
|
// relative to reading lines via stream reader
|
||||||
|
if (!string.IsNullOrEmpty(fileInfo.PhysicalPath))
|
||||||
|
{
|
||||||
|
lines = File.ReadLines(fileInfo.PhysicalPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lines = ReadLines(fileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines != null)
|
||||||
|
{
|
||||||
|
ReadFrameContent(frame, lines, lineNumber, lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadFrameContent(StackFrame frame,
|
// make it internal to enable unit testing
|
||||||
IEnumerable<string> code,
|
internal void ReadFrameContent(
|
||||||
int startLineNumber,
|
StackFrame frame,
|
||||||
int endLineNumber)
|
IEnumerable<string> allLines,
|
||||||
|
int errorStartLineNumberInFile,
|
||||||
|
int errorEndLineNumberInFile)
|
||||||
{
|
{
|
||||||
frame.PreContextLine = Math.Max(startLineNumber - _options.SourceCodeLineCount, 1);
|
// Get the line boundaries in the file to be read and read all these lines at once into an array.
|
||||||
frame.PreContextCode = code.Skip(frame.PreContextLine - 1).Take(startLineNumber - frame.PreContextLine).ToArray();
|
var preErrorLineNumberInFile = Math.Max(errorStartLineNumberInFile - _options.SourceCodeLineCount, 1);
|
||||||
frame.ContextCode = code.Skip(startLineNumber - 1).Take(1 + Math.Max(0, endLineNumber - startLineNumber));
|
var postErrorLineNumberInFile = errorEndLineNumberInFile + _options.SourceCodeLineCount;
|
||||||
frame.PostContextCode = code.Skip(startLineNumber).Take(_options.SourceCodeLineCount).ToArray();
|
var codeBlock = allLines
|
||||||
|
.Skip(preErrorLineNumberInFile - 1)
|
||||||
|
.Take(postErrorLineNumberInFile - preErrorLineNumberInFile + 1)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var numOfErrorLines = (errorEndLineNumberInFile - errorStartLineNumberInFile) + 1;
|
||||||
|
var errorStartLineNumberInArray = errorStartLineNumberInFile - preErrorLineNumberInFile;
|
||||||
|
|
||||||
|
frame.PreContextLine = preErrorLineNumberInFile;
|
||||||
|
frame.PreContextCode = codeBlock.Take(errorStartLineNumberInArray).ToArray();
|
||||||
|
frame.ContextCode = codeBlock
|
||||||
|
.Skip(errorStartLineNumberInArray)
|
||||||
|
.Take(numOfErrorLines)
|
||||||
|
.ToArray();
|
||||||
|
frame.PostContextCode = codeBlock
|
||||||
|
.Skip(errorStartLineNumberInArray + numOfErrorLines)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> ReadLines(IFileInfo fileInfo)
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
while ((line = reader.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
yield return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Chunk
|
internal class Chunk
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
using Microsoft.AspNet.FileProviders;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Diagnostics
|
namespace Microsoft.AspNet.Diagnostics
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -23,5 +25,13 @@ namespace Microsoft.AspNet.Diagnostics
|
||||||
/// source code referenced by the exception stack trace is present on the server.
|
/// source code referenced by the exception stack trace is present on the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SourceCodeLineCount { get; set; }
|
public int SourceCodeLineCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides files containing source code used to display contextual information of an exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If <c>null</c> <see cref="ErrorPageMiddleware" /> will use a <see cref="PhysicalFileProvider"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public IFileProvider FileProvider { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,8 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <li class=\"frame\"");
|
WriteLiteral(" <li class=\"frame\"");
|
||||||
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 1231), Tuple.Create("\"", 1251),
|
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 1246), Tuple.Create("\"", 1266),
|
||||||
Tuple.Create(Tuple.Create("", 1242), Tuple.Create<System.Object, System.Int32>(tabIndex, 1242), false));
|
Tuple.Create(Tuple.Create("", 1257), Tuple.Create<System.Object, System.Int32>(tabIndex, 1257), false));
|
||||||
WriteLiteral(">\r\n");
|
WriteLiteral(">\r\n");
|
||||||
#line 42 "CompilationErrorPage.cshtml"
|
#line 42 "CompilationErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 48 "CompilationErrorPage.cshtml"
|
#line 48 "CompilationErrorPage.cshtml"
|
||||||
if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
if (frame.Line != 0 && frame.ContextCode.Any())
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
|
|
@ -207,15 +207,15 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 51 "CompilationErrorPage.cshtml"
|
#line 51 "CompilationErrorPage.cshtml"
|
||||||
if (frame.PreContextCode != null)
|
if (frame.PreContextCode.Any())
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <ol");
|
WriteLiteral(" <ol");
|
||||||
WriteAttribute("start", Tuple.Create(" start=\"", 1777), Tuple.Create("\"", 1806),
|
WriteAttribute("start", Tuple.Create(" start=\"", 1790), Tuple.Create("\"", 1819),
|
||||||
Tuple.Create(Tuple.Create("", 1785), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 1785), false));
|
Tuple.Create(Tuple.Create("", 1798), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 1798), false));
|
||||||
WriteLiteral(" class=\"collapsible\">\r\n");
|
WriteLiteral(" class=\"collapsible\">\r\n");
|
||||||
#line 54 "CompilationErrorPage.cshtml"
|
#line 54 "CompilationErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
@ -251,8 +251,8 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <ol");
|
WriteLiteral(" <ol");
|
||||||
WriteAttribute("start", Tuple.Create(" start=\"", 2187), Tuple.Create("\"", 2206),
|
WriteAttribute("start", Tuple.Create(" start=\"", 2200), Tuple.Create("\"", 2219),
|
||||||
Tuple.Create(Tuple.Create("", 2195), Tuple.Create<System.Object, System.Int32>(frame.Line, 2195), false));
|
Tuple.Create(Tuple.Create("", 2208), Tuple.Create<System.Object, System.Int32>(frame.Line, 2208), false));
|
||||||
WriteLiteral(" class=\"highlight\">\r\n");
|
WriteLiteral(" class=\"highlight\">\r\n");
|
||||||
#line 61 "CompilationErrorPage.cshtml"
|
#line 61 "CompilationErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
@ -288,15 +288,15 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 66 "CompilationErrorPage.cshtml"
|
#line 66 "CompilationErrorPage.cshtml"
|
||||||
if (frame.PostContextCode != null)
|
if (frame.PostContextCode.Any())
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <ol");
|
WriteLiteral(" <ol");
|
||||||
WriteAttribute("start", Tuple.Create(" start=\'", 2635), Tuple.Create("\'", 2660),
|
WriteAttribute("start", Tuple.Create(" start=\'", 2646), Tuple.Create("\'", 2671),
|
||||||
Tuple.Create(Tuple.Create("", 2643), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 2643), false));
|
Tuple.Create(Tuple.Create("", 2654), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 2654), false));
|
||||||
WriteLiteral(" class=\"collapsible\">\r\n");
|
WriteLiteral(" class=\"collapsible\">\r\n");
|
||||||
#line 69 "CompilationErrorPage.cshtml"
|
#line 69 "CompilationErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,10 @@
|
||||||
<h3>@frame.ErrorDetails</h3>
|
<h3>@frame.ErrorDetails</h3>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
@if (frame.Line != 0 && frame.ContextCode.Any())
|
||||||
{
|
{
|
||||||
<div class="source">
|
<div class="source">
|
||||||
@if (frame.PreContextCode != null)
|
@if (frame.PreContextCode.Any())
|
||||||
{
|
{
|
||||||
<ol start="@frame.PreContextLine" class="collapsible">
|
<ol start="@frame.PreContextLine" class="collapsible">
|
||||||
@foreach (var line in frame.PreContextCode)
|
@foreach (var line in frame.PreContextCode)
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
<li><span>@line</span></li>
|
<li><span>@line</span></li>
|
||||||
}
|
}
|
||||||
</ol>
|
</ol>
|
||||||
@if (frame.PostContextCode != null)
|
@if (frame.PostContextCode.Any())
|
||||||
{
|
{
|
||||||
<ol start='@(frame.Line + 1)' class="collapsible">
|
<ol start='@(frame.Line + 1)' class="collapsible">
|
||||||
@foreach (var line in frame.PostContextCode)
|
@foreach (var line in frame.PostContextCode)
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral("\r\n<!DOCTYPE html>\r\n<html");
|
WriteLiteral("\r\n<!DOCTYPE html>\r\n<html");
|
||||||
WriteAttribute("lang", Tuple.Create(" lang=\"", 518), Tuple.Create("\"", 579),
|
WriteAttribute("lang", Tuple.Create(" lang=\"", 533), Tuple.Create("\"", 594),
|
||||||
Tuple.Create(Tuple.Create("", 525), Tuple.Create<System.Object, System.Int32>(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, 525), false));
|
Tuple.Create(Tuple.Create("", 540), Tuple.Create<System.Object, System.Int32>(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, 540), false));
|
||||||
WriteLiteral(" xmlns=\"http://www.w3.org/1999/xhtml\">\r\n <head>\r\n <meta charset=\"utf-8\"" +
|
WriteLiteral(" xmlns=\"http://www.w3.org/1999/xhtml\">\r\n <head>\r\n <meta charset=\"utf-8\"" +
|
||||||
" />\r\n <title>");
|
" />\r\n <title>");
|
||||||
#line 26 "ErrorPage.cshtml"
|
#line 26 "ErrorPage.cshtml"
|
||||||
|
|
@ -147,8 +147,8 @@ using Views
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral(" in <code");
|
WriteLiteral(" in <code");
|
||||||
WriteAttribute("title", Tuple.Create(" title=\"", 1895), Tuple.Create("\"", 1919),
|
WriteAttribute("title", Tuple.Create(" title=\"", 1910), Tuple.Create("\"", 1934),
|
||||||
Tuple.Create(Tuple.Create("", 1903), Tuple.Create<System.Object, System.Int32>(firstFrame.File, 1903), false));
|
Tuple.Create(Tuple.Create("", 1918), Tuple.Create<System.Object, System.Int32>(firstFrame.File, 1918), false));
|
||||||
WriteLiteral(">");
|
WriteLiteral(">");
|
||||||
#line 50 "ErrorPage.cshtml"
|
#line 50 "ErrorPage.cshtml"
|
||||||
Write(System.IO.Path.GetFileName(firstFrame.File));
|
Write(System.IO.Path.GetFileName(firstFrame.File));
|
||||||
|
|
@ -281,8 +281,8 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <li class=\"frame\"");
|
WriteLiteral(" <li class=\"frame\"");
|
||||||
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 3327), Tuple.Create("\"", 3347),
|
WriteAttribute("tabindex", Tuple.Create(" tabindex=\"", 3342), Tuple.Create("\"", 3362),
|
||||||
Tuple.Create(Tuple.Create("", 3338), Tuple.Create<System.Object, System.Int32>(tabIndex, 3338), false));
|
Tuple.Create(Tuple.Create("", 3353), Tuple.Create<System.Object, System.Int32>(tabIndex, 3353), false));
|
||||||
WriteLiteral(">\r\n");
|
WriteLiteral(">\r\n");
|
||||||
#line 87 "ErrorPage.cshtml"
|
#line 87 "ErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
@ -332,8 +332,8 @@ using Views
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
WriteLiteral(" in <code");
|
WriteLiteral(" in <code");
|
||||||
WriteAttribute("title", Tuple.Create(" title=\"", 3742), Tuple.Create("\"", 3761),
|
WriteAttribute("title", Tuple.Create(" title=\"", 3757), Tuple.Create("\"", 3776),
|
||||||
Tuple.Create(Tuple.Create("", 3750), Tuple.Create<System.Object, System.Int32>(frame.File, 3750), false));
|
Tuple.Create(Tuple.Create("", 3765), Tuple.Create<System.Object, System.Int32>(frame.File, 3765), false));
|
||||||
WriteLiteral(">");
|
WriteLiteral(">");
|
||||||
#line 94 "ErrorPage.cshtml"
|
#line 94 "ErrorPage.cshtml"
|
||||||
Write(System.IO.Path.GetFileName(frame.File));
|
Write(System.IO.Path.GetFileName(frame.File));
|
||||||
|
|
@ -355,7 +355,7 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 97 "ErrorPage.cshtml"
|
#line 97 "ErrorPage.cshtml"
|
||||||
if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
if (frame.Line != 0 && frame.ContextCode.Any())
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
|
|
@ -369,15 +369,15 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 100 "ErrorPage.cshtml"
|
#line 100 "ErrorPage.cshtml"
|
||||||
if (frame.PreContextCode != null)
|
if (frame.PreContextCode.Any())
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <ol");
|
WriteLiteral(" <ol");
|
||||||
WriteAttribute("start", Tuple.Create(" start=\"", 4194), Tuple.Create("\"", 4223),
|
WriteAttribute("start", Tuple.Create(" start=\"", 4207), Tuple.Create("\"", 4236),
|
||||||
Tuple.Create(Tuple.Create("", 4202), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 4202), false));
|
Tuple.Create(Tuple.Create("", 4215), Tuple.Create<System.Object, System.Int32>(frame.PreContextLine, 4215), false));
|
||||||
WriteLiteral(" class=\"collapsible\">\r\n");
|
WriteLiteral(" class=\"collapsible\">\r\n");
|
||||||
#line 103 "ErrorPage.cshtml"
|
#line 103 "ErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
@ -413,8 +413,8 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral("\r\n <ol");
|
WriteLiteral("\r\n <ol");
|
||||||
WriteAttribute("start", Tuple.Create(" start=\"", 4663), Tuple.Create("\"", 4682),
|
WriteAttribute("start", Tuple.Create(" start=\"", 4676), Tuple.Create("\"", 4695),
|
||||||
Tuple.Create(Tuple.Create("", 4671), Tuple.Create<System.Object, System.Int32>(frame.Line, 4671), false));
|
Tuple.Create(Tuple.Create("", 4684), Tuple.Create<System.Object, System.Int32>(frame.Line, 4684), false));
|
||||||
WriteLiteral(" class=\"highlight\">\r\n");
|
WriteLiteral(" class=\"highlight\">\r\n");
|
||||||
#line 111 "ErrorPage.cshtml"
|
#line 111 "ErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
@ -450,15 +450,15 @@ using Views
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
#line 117 "ErrorPage.cshtml"
|
#line 117 "ErrorPage.cshtml"
|
||||||
if (frame.PostContextCode != null)
|
if (frame.PostContextCode.Any())
|
||||||
{
|
{
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
|
|
||||||
WriteLiteral(" <ol");
|
WriteLiteral(" <ol");
|
||||||
WriteAttribute("start", Tuple.Create(" start=\'", 5177), Tuple.Create("\'", 5202),
|
WriteAttribute("start", Tuple.Create(" start=\'", 5188), Tuple.Create("\'", 5213),
|
||||||
Tuple.Create(Tuple.Create("", 5185), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 5185), false));
|
Tuple.Create(Tuple.Create("", 5196), Tuple.Create<System.Object, System.Int32>(frame.Line + 1, 5196), false));
|
||||||
WriteLiteral(" class=\"collapsible\">\r\n");
|
WriteLiteral(" class=\"collapsible\">\r\n");
|
||||||
#line 120 "ErrorPage.cshtml"
|
#line 120 "ErrorPage.cshtml"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,10 @@
|
||||||
<h3>@frame.Function in <code title="@frame.File">@System.IO.Path.GetFileName(frame.File)</code></h3>
|
<h3>@frame.Function in <code title="@frame.File">@System.IO.Path.GetFileName(frame.File)</code></h3>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (frame.Line != 0 && frame.ContextCode !=null && frame.ContextCode.Any())
|
@if (frame.Line != 0 && frame.ContextCode.Any())
|
||||||
{
|
{
|
||||||
<div class="source">
|
<div class="source">
|
||||||
@if (frame.PreContextCode != null)
|
@if (frame.PreContextCode.Any())
|
||||||
{
|
{
|
||||||
<ol start="@frame.PreContextLine" class="collapsible">
|
<ol start="@frame.PreContextLine" class="collapsible">
|
||||||
@foreach (var line in frame.PreContextCode)
|
@foreach (var line in frame.PreContextCode)
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
}
|
}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
@if (frame.PostContextCode != null)
|
@if (frame.PostContextCode.Any())
|
||||||
{
|
{
|
||||||
<ol start='@(frame.Line + 1)' class="collapsible">
|
<ol start='@(frame.Line + 1)' class="collapsible">
|
||||||
@foreach (var line in frame.PostContextCode)
|
@foreach (var line in frame.PostContextCode)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Diagnostics.Views
|
namespace Microsoft.AspNet.Diagnostics.Views
|
||||||
{
|
{
|
||||||
|
|
@ -32,19 +33,19 @@ namespace Microsoft.AspNet.Diagnostics.Views
|
||||||
public int PreContextLine { get; set; }
|
public int PreContextLine { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Lines of code before the actual error line(s).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> PreContextCode { get; set; }
|
public IEnumerable<string> PreContextCode { get; set; } = Enumerable.Empty<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Line(s) of code responsible for the error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> ContextCode { get; set; }
|
public IEnumerable<string> ContextCode { get; set; } = Enumerable.Empty<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Lines of code after the actual error line(s).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> PostContextCode { get; set; }
|
public IEnumerable<string> PostContextCode { get; set; } = Enumerable.Empty<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specific error details for this stack frame.
|
/// Specific error details for this stack frame.
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,17 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Diagnostics.Abstractions": "1.0.0-*",
|
"Microsoft.AspNet.Diagnostics.Abstractions": "1.0.0-*",
|
||||||
|
"Microsoft.AspNet.FileProviders.Physical": "1.0.0-*",
|
||||||
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
|
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
|
||||||
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
|
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
|
||||||
|
"Microsoft.Framework.Logging.Abstractions": "1.0.0-*",
|
||||||
|
"Microsoft.Framework.NotNullAttribute.Sources": {
|
||||||
|
"type": "build",
|
||||||
|
"version": "1.0.0-*"
|
||||||
|
},
|
||||||
"Microsoft.Framework.OptionsModel": "1.0.0-*",
|
"Microsoft.Framework.OptionsModel": "1.0.0-*",
|
||||||
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" },
|
|
||||||
"Microsoft.Framework.WebEncoders.Core": "1.0.0-*",
|
|
||||||
"Microsoft.Framework.Runtime.Compilation.Abstractions": "1.0.0-*",
|
"Microsoft.Framework.Runtime.Compilation.Abstractions": "1.0.0-*",
|
||||||
"Microsoft.Framework.Logging.Abstractions": "1.0.0-*"
|
"Microsoft.Framework.WebEncoders.Core": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnx451": {},
|
"dnx451": {},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,451 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Diagnostics.Views;
|
||||||
|
using Microsoft.AspNet.FileProviders;
|
||||||
|
using Microsoft.Framework.Caching;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.Runtime;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Diagnostics
|
||||||
|
{
|
||||||
|
public class ErrorPageMiddlewareTest
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData("TestFiles/SourceFile.txt")]
|
||||||
|
[InlineData(@"TestFiles\SourceFile.txt")]
|
||||||
|
public void UsesDefaultFileProvider_IfNotProvidedOnOptions(string relativePath)
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var middleware = GetErrorPageMiddleware(fileProvider: null);
|
||||||
|
var stackFrame = middleware.GetStackFrame("func1", relativePath, lineNumber: 10);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Lines 4-16 (inclusive) is the code block
|
||||||
|
Assert.Equal(4, stackFrame.PreContextLine);
|
||||||
|
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData<string> AbsolutePathsData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var rootPath = Directory.GetCurrentDirectory();
|
||||||
|
return new TheoryData<string>()
|
||||||
|
{
|
||||||
|
Path.Combine(rootPath, "TestFiles/SourceFile.txt"),
|
||||||
|
Path.Combine(rootPath, @"TestFiles\SourceFile.txt")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(AbsolutePathsData))]
|
||||||
|
public void DisplaysSourceCodeLines_ForAbsolutePaths(string absoluteFilePath)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var rootPath = Directory.GetCurrentDirectory();
|
||||||
|
// PhysicalFileProvider handles only relative paths but we fall back to work with absolute paths too
|
||||||
|
var provider = new PhysicalFileProvider(rootPath);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var middleware = GetErrorPageMiddleware(provider);
|
||||||
|
var stackFrame = middleware.GetStackFrame("func1", absoluteFilePath, lineNumber: 10);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Lines 4-16 (inclusive) is the code block
|
||||||
|
Assert.Equal(4, stackFrame.PreContextLine);
|
||||||
|
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("TestFiles/SourceFile.txt")]
|
||||||
|
[InlineData(@"TestFiles\SourceFile.txt")]
|
||||||
|
public void DisplaysSourceCodeLines_ForRelativePaths(string relativePath)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var rootPath = Directory.GetCurrentDirectory();
|
||||||
|
var provider = new PhysicalFileProvider(rootPath);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var middleware = GetErrorPageMiddleware(provider);
|
||||||
|
var stackFrame = middleware.GetStackFrame("func1", relativePath, lineNumber: 10);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Lines 4-16 (inclusive) is the code block
|
||||||
|
Assert.Equal(4, stackFrame.PreContextLine);
|
||||||
|
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("TestFiles/EmbeddedSourceFile.txt")]
|
||||||
|
//[InlineData(@"TestFiles\EmbeddedSourceFile.txt")]
|
||||||
|
public void DisplaysSourceCodeLines_ForRelativeEmbeddedPaths(string relativePath)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var provider = new EmbeddedFileProvider(
|
||||||
|
GetType().GetTypeInfo().Assembly,
|
||||||
|
baseNamespace: $"{typeof(ErrorPageMiddlewareTest).GetTypeInfo().Assembly.GetName().Name}.Resources");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var middleware = GetErrorPageMiddleware(provider);
|
||||||
|
var stackFrame = middleware.GetStackFrame("func1", relativePath, lineNumber: 10);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Lines 4-16 (inclusive) is the code block
|
||||||
|
Assert.Equal(4, stackFrame.PreContextLine);
|
||||||
|
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
|
||||||
|
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData<ErrorData> DisplaysSourceCodeLines_PreAndPostErrorLineData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<ErrorData>()
|
||||||
|
{
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 30),
|
||||||
|
ErrorStartLine = 10,
|
||||||
|
ErrorEndLine = 10,
|
||||||
|
ExpectedPreContextLine = 4,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(4, 9),
|
||||||
|
ExpectedErrorCode = GetCodeLines(10, 10),
|
||||||
|
ExpectedPostErrorCode = GetCodeLines(11, 16)
|
||||||
|
},
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 30),
|
||||||
|
ErrorStartLine = 10,
|
||||||
|
ErrorEndLine = 13, // multi-line error
|
||||||
|
ExpectedPreContextLine = 4,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(4, 9),
|
||||||
|
ExpectedErrorCode = GetCodeLines(10, 13),
|
||||||
|
ExpectedPostErrorCode = GetCodeLines(14, 19)
|
||||||
|
},
|
||||||
|
|
||||||
|
// PreErrorCode less than source code line count
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 10),
|
||||||
|
ErrorStartLine = 1,
|
||||||
|
ErrorEndLine = 1,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = Enumerable.Empty<string>(),
|
||||||
|
ExpectedErrorCode = GetCodeLines(1, 1),
|
||||||
|
ExpectedPostErrorCode = GetCodeLines(2, 7)
|
||||||
|
},
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 10),
|
||||||
|
ErrorStartLine = 3,
|
||||||
|
ErrorEndLine = 5,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(1, 2),
|
||||||
|
ExpectedErrorCode = GetCodeLines(3, 5),
|
||||||
|
ExpectedPostErrorCode = GetCodeLines(6, 10)
|
||||||
|
},
|
||||||
|
|
||||||
|
// PostErrorCode less than source code line count
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 10),
|
||||||
|
ErrorStartLine = 10,
|
||||||
|
ErrorEndLine = 10,
|
||||||
|
ExpectedPreContextLine = 4,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(4, 9),
|
||||||
|
ExpectedErrorCode = GetCodeLines(10, 10),
|
||||||
|
ExpectedPostErrorCode = Enumerable.Empty<string>()
|
||||||
|
},
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 10),
|
||||||
|
ErrorStartLine = 7,
|
||||||
|
ErrorEndLine = 10,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(1, 6),
|
||||||
|
ExpectedErrorCode = GetCodeLines(7, 10),
|
||||||
|
ExpectedPostErrorCode = Enumerable.Empty<string>()
|
||||||
|
},
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 10),
|
||||||
|
ErrorStartLine = 5,
|
||||||
|
ErrorEndLine = 8,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(1, 4),
|
||||||
|
ExpectedErrorCode = GetCodeLines(5, 8),
|
||||||
|
ExpectedPostErrorCode = GetCodeLines(9, 10)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Pre and Post error code less than source code line count
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 4),
|
||||||
|
ErrorStartLine = 2,
|
||||||
|
ErrorEndLine = 3,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = GetCodeLines(1, 1),
|
||||||
|
ExpectedErrorCode = GetCodeLines(2, 3),
|
||||||
|
ExpectedPostErrorCode = GetCodeLines(4, 4)
|
||||||
|
},
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
AllLines = GetCodeLines(1, 4),
|
||||||
|
ErrorStartLine = 1,
|
||||||
|
ErrorEndLine = 4,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = Enumerable.Empty<string>(),
|
||||||
|
ExpectedErrorCode = GetCodeLines(1, 4),
|
||||||
|
ExpectedPostErrorCode = Enumerable.Empty<string>()
|
||||||
|
},
|
||||||
|
|
||||||
|
// change source code line count
|
||||||
|
new ErrorData()
|
||||||
|
{
|
||||||
|
SourceCodeLineCount = 1,
|
||||||
|
AllLines = GetCodeLines(1, 1),
|
||||||
|
ErrorStartLine = 1,
|
||||||
|
ErrorEndLine = 1,
|
||||||
|
ExpectedPreContextLine = 1,
|
||||||
|
ExpectedPreErrorCode = Enumerable.Empty<string>(),
|
||||||
|
ExpectedErrorCode = GetCodeLines(1, 1),
|
||||||
|
ExpectedPostErrorCode = Enumerable.Empty<string>()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(DisplaysSourceCodeLines_PreAndPostErrorLineData))]
|
||||||
|
public void DisplaysSourceCodeLines_PreAndPostErrorLine(ErrorData errorData)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var middleware = GetErrorPageMiddleware();
|
||||||
|
var stackFrame = new StackFrame();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
middleware.ReadFrameContent(
|
||||||
|
stackFrame, errorData.AllLines, errorData.ErrorStartLine, errorData.ErrorEndLine);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(errorData.ExpectedPreContextLine, stackFrame.PreContextLine);
|
||||||
|
Assert.Equal(errorData.ExpectedPreErrorCode, stackFrame.PreContextCode);
|
||||||
|
Assert.Equal(errorData.ExpectedErrorCode, stackFrame.ContextCode);
|
||||||
|
Assert.Equal(errorData.ExpectedPostErrorCode, stackFrame.PostContextCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GetCodeLines(int fromLine, int toLine)
|
||||||
|
{
|
||||||
|
var start = fromLine;
|
||||||
|
var count = toLine - fromLine + 1;
|
||||||
|
return Enumerable.Range(start, count).Select(i => string.Format("Line{0}", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ErrorPageMiddleware GetErrorPageMiddleware(
|
||||||
|
IFileProvider fileProvider = null, int sourceCodeLineCount = 6)
|
||||||
|
{
|
||||||
|
var errorPageOptions = new ErrorPageOptions();
|
||||||
|
errorPageOptions.SourceCodeLineCount = sourceCodeLineCount;
|
||||||
|
|
||||||
|
if (fileProvider != null)
|
||||||
|
{
|
||||||
|
errorPageOptions.FileProvider = fileProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
var middleware = new ErrorPageMiddleware(
|
||||||
|
(httpContext) => { return Task.FromResult(0); },
|
||||||
|
errorPageOptions,
|
||||||
|
new LoggerFactory(),
|
||||||
|
new TestApplicationEnvironment());
|
||||||
|
|
||||||
|
return middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestApplicationEnvironment : IApplicationEnvironment
|
||||||
|
{
|
||||||
|
public string ApplicationBasePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Directory.GetCurrentDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ApplicationName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ApplicationVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Configuration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameworkName RuntimeFramework
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetData(string name)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetData(string name, object value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestFileProvider : IFileProvider
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<string> _sourceCodeLines;
|
||||||
|
|
||||||
|
public TestFileProvider(IEnumerable<string> sourceCodeLines)
|
||||||
|
{
|
||||||
|
_sourceCodeLines = sourceCodeLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDirectoryContents GetDirectoryContents(string subpath)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFileInfo GetFileInfo(string subpath)
|
||||||
|
{
|
||||||
|
return new TestFileInfo(_sourceCodeLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IExpirationTrigger Watch(string filter)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestFileInfo : IFileInfo
|
||||||
|
{
|
||||||
|
private readonly MemoryStream _stream;
|
||||||
|
|
||||||
|
public TestFileInfo(IEnumerable<string> sourceCodeLines)
|
||||||
|
{
|
||||||
|
_stream = new MemoryStream();
|
||||||
|
using (var writer = new StreamWriter(_stream, Encoding.UTF8, 1024, leaveOpen: true))
|
||||||
|
{
|
||||||
|
foreach (var line in sourceCodeLines)
|
||||||
|
{
|
||||||
|
writer.WriteLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Exists
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDirectory
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeOffset LastModified
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Length
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PhysicalPath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream CreateReadStream()
|
||||||
|
{
|
||||||
|
return _stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ErrorData
|
||||||
|
{
|
||||||
|
public int SourceCodeLineCount { get; set; } = 6;
|
||||||
|
public IEnumerable<string> AllLines { get; set; }
|
||||||
|
public int ErrorStartLine { get; set; }
|
||||||
|
public int ErrorEndLine { get; set; }
|
||||||
|
public int ExpectedPreContextLine { get; set; }
|
||||||
|
public IEnumerable<string> ExpectedPreErrorCode { get; set; }
|
||||||
|
public IEnumerable<string> ExpectedErrorCode { get; set; }
|
||||||
|
public IEnumerable<string> ExpectedPostErrorCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
Line1
|
||||||
|
Line2
|
||||||
|
Line3
|
||||||
|
Line4
|
||||||
|
Line5
|
||||||
|
Line6
|
||||||
|
Line7
|
||||||
|
Line8
|
||||||
|
Line9
|
||||||
|
Line10
|
||||||
|
Line11
|
||||||
|
Line12
|
||||||
|
Line13
|
||||||
|
Line14
|
||||||
|
Line15
|
||||||
|
Line16
|
||||||
|
Line17
|
||||||
|
Line18
|
||||||
|
Line19
|
||||||
|
Line20
|
||||||
|
Line21
|
||||||
|
Line22
|
||||||
|
Line23
|
||||||
|
Line24
|
||||||
|
Line25
|
||||||
|
Line26
|
||||||
|
Line27
|
||||||
|
Line28
|
||||||
|
Line29
|
||||||
|
Line30
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
Line1
|
||||||
|
Line2
|
||||||
|
Line3
|
||||||
|
Line4
|
||||||
|
Line5
|
||||||
|
Line6
|
||||||
|
Line7
|
||||||
|
Line8
|
||||||
|
Line9
|
||||||
|
Line10
|
||||||
|
Line11
|
||||||
|
Line12
|
||||||
|
Line13
|
||||||
|
Line14
|
||||||
|
Line15
|
||||||
|
Line16
|
||||||
|
Line17
|
||||||
|
Line18
|
||||||
|
Line19
|
||||||
|
Line20
|
||||||
|
Line21
|
||||||
|
Line22
|
||||||
|
Line23
|
||||||
|
Line24
|
||||||
|
Line25
|
||||||
|
Line26
|
||||||
|
Line27
|
||||||
|
Line28
|
||||||
|
Line29
|
||||||
|
Line30
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Diagnostics.Elm": "1.0.0-*",
|
"Microsoft.AspNet.Diagnostics.Elm": "1.0.0-*",
|
||||||
|
"Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*",
|
||||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||||
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
|
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
|
||||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||||
|
|
@ -18,7 +19,10 @@
|
||||||
"dnxcore50": {
|
"dnxcore50": {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"commands": {
|
"commands": {
|
||||||
"test": "xunit.runner.aspnet"
|
"test": "xunit.runner.aspnet"
|
||||||
}
|
},
|
||||||
|
|
||||||
|
"resource": [ "Resources/**" ]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue