Merge pull request #32 from christiang88/ReduceMemoryConsumption
Reduce memory consumption
This commit is contained in:
Коммит
0ff79ec40a
|
@ -31,14 +31,18 @@ TypeError: Cannot read property 'length' of undefined
|
|||
SourcePosition.ZeroBasedLineNumber: 5
|
||||
```
|
||||
### Usage
|
||||
The top level API for call stack deminification is the `StackTraceDeminifier.DeminifyStackTrace` method. For each url that appears in a JavaScript callstack, the library requires the contents of the JavaScript file and corresponding source map in order to determine the original method name and code location. This information is provided by the consumer of the API by implementing the `ISourceMapProvider` and `ISourceCodeProvider` interfaces. These interfaces are expected to return a `StreamReader` that can be used to access the contents of the requested JavaScript code or corresponding source map. A sample usage of the library is shown below
|
||||
The top level API for call stack deminification is the `StackTraceDeminifier.DeminifyStackTrace` method. For each url that appears in a JavaScript callstack, the library requires the contents of the JavaScript file and corresponding source map in order to determine the original method name and code location. This information is provided by the consumer of the API by implementing the `ISourceMapProvider` and `ISourceCodeProvider` interfaces. These interfaces are expected to return a `StreamReader` that can be used to access the contents of the requested JavaScript code or corresponding source map. A `StackTraceDeminifier` can be instantiated using one of the methods on `StackTraceDeminfierFactory`. A sample usage of the library is shown below.
|
||||
|
||||
```csharp
|
||||
StackTraceDeminifier sourceMapCallstackDeminifier = new StackTraceDeminifier(new SourceMapProvider(), new SourceCodeProvider());
|
||||
StackTraceDeminifier sourceMapCallstackDeminifier = StackTraceDeminfierFactory.GetStackTraceDeminfier(new SourceMapProvider(), new SourceCodeProvider());
|
||||
DeminifyStackTraceResult deminifyStackTraceResult = sourceMapCallstackDeminifier.DeminifyStackTrace(callstack)
|
||||
```
|
||||
|
||||
The result of `DeminifyStackTrace` is a `DeminifyStackTraceResult`, which is an object that contains a list of the parsed minified `StackFrame` objects in the `MinifiedStackFrame` property. The `DeminifiedStackFrame` property contains the best guess `StackFrame` object that maps to the `MinifiedStackFrame` element with the same index. Note that any of the properties on a `StackTrace` object may be null if no value could be extracted from the input callstack string or source map.
|
||||
|
||||
#### Memory Consumption
|
||||
Parsed soure maps can take up a lot of memory for large JavaScript files. In order to allow for the `StackTraceDeminifier` to be used on servers with limited memory resources, the `StackTraceDeminfierFactory` exposes a `GetMethodNameOnlyStackTraceDeminfier` method that returns a `StackTraceDeminifier` that does not keep source maps in memory. Since the `StackTraceDeminifier` returned from this method only reads the source map once, the deminified stack frames will only contain the deminified method name and will not contain the original source location.
|
||||
|
||||
## Remarks
|
||||
Browsers return one based line and column numbers, while the source map spec calls for zero based line and column numbers. In order to minimize confusion, line and column numbers are normalized to be zero based throughout the library.
|
||||
|
||||
|
|
|
@ -30,7 +30,13 @@ namespace SourcemapToolkit.CallstackDeminifier
|
|||
/// To get the complete name of the function associated with this mapping entry
|
||||
/// append the names of each bindings with a "."
|
||||
/// </summary>
|
||||
public List<BindingInformation> Bindings { get; set; }
|
||||
public List<BindingInformation> Bindings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this entry represents a function whose name was minified, this value
|
||||
/// may contain an associated deminfied name corresponding to the function.
|
||||
/// </summary>
|
||||
public string DeminfifiedMethodName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Denotes the location of the beginning of this function
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Ajax.Utilities;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
|
@ -10,7 +12,27 @@ namespace SourcemapToolkit.CallstackDeminifier
|
|||
/// Returns a FunctionMap describing the locations of every funciton in the source code.
|
||||
/// The functions are to be sorted descending by start position.
|
||||
/// </summary>
|
||||
public List<FunctionMapEntry> GenerateFunctionMap(StreamReader sourceCodeStreamReader)
|
||||
public List<FunctionMapEntry> GenerateFunctionMap(StreamReader sourceCodeStreamReader, SourceMap sourceMap)
|
||||
{
|
||||
if (sourceCodeStreamReader == null || sourceMap == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<FunctionMapEntry> result = ParseSourceCode(sourceCodeStreamReader);
|
||||
|
||||
foreach (FunctionMapEntry functionMapEntry in result)
|
||||
{
|
||||
functionMapEntry.DeminfifiedMethodName = GetDeminifiedMethodNameFromSourceMap(functionMapEntry, sourceMap);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over all the code in the JavaScript file to get a list of all the functions declared in that file.
|
||||
/// </summary>
|
||||
internal List<FunctionMapEntry> ParseSourceCode(StreamReader sourceCodeStreamReader)
|
||||
{
|
||||
if (sourceCodeStreamReader == null)
|
||||
{
|
||||
|
@ -32,7 +54,47 @@ namespace SourcemapToolkit.CallstackDeminifier
|
|||
|
||||
// Sort in descending order by start position
|
||||
functionFinderVisitor.FunctionMap.Sort((x, y) => y.StartSourcePosition.CompareTo(x.StartSourcePosition));
|
||||
|
||||
return functionFinderVisitor.FunctionMap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original name corresponding to a function based on the information provided in the source map.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetDeminifiedMethodNameFromSourceMap(FunctionMapEntry wrappingFunction, SourceMap sourceMap)
|
||||
{
|
||||
string methodName = null;
|
||||
|
||||
if (wrappingFunction?.Bindings != null && wrappingFunction.Bindings.Count > 0)
|
||||
{
|
||||
if (wrappingFunction.Bindings.Count == 2)
|
||||
{
|
||||
MappingEntry objectProtoypeMappingEntry =
|
||||
sourceMap?.GetMappingEntryForGeneratedSourcePosition(wrappingFunction.Bindings[0].SourcePosition);
|
||||
|
||||
methodName = objectProtoypeMappingEntry?.OriginalName;
|
||||
}
|
||||
|
||||
MappingEntry mappingEntry =
|
||||
sourceMap?.GetMappingEntryForGeneratedSourcePosition(wrappingFunction.Bindings.Last().SourcePosition);
|
||||
|
||||
if (mappingEntry != null)
|
||||
{
|
||||
if (mappingEntry.OriginalName != null)
|
||||
{
|
||||
if (methodName != null)
|
||||
{
|
||||
methodName = methodName + "." + mappingEntry.OriginalName;
|
||||
}
|
||||
else
|
||||
{
|
||||
methodName = mappingEntry.OriginalName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return methodName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
|
@ -7,16 +9,15 @@ namespace SourcemapToolkit.CallstackDeminifier
|
|||
/// </summary>
|
||||
internal class FunctionMapStore : IFunctionMapStore
|
||||
{
|
||||
private readonly ISourceCodeProvider _sourceCodeProvider;
|
||||
private readonly IFunctionMapGenerator _functionMapGenerator;
|
||||
private readonly KeyValueCache<string,List<FunctionMapEntry>> _functionMapCache;
|
||||
|
||||
public FunctionMapStore(ISourceCodeProvider sourceCodeProvider)
|
||||
public FunctionMapStore(ISourceCodeProvider sourceCodeProvider, Func<string, SourceMap> sourceMapGetter)
|
||||
{
|
||||
_sourceCodeProvider = sourceCodeProvider;
|
||||
_functionMapGenerator = new FunctionMapGenerator();
|
||||
_functionMapCache = new KeyValueCache<string, List<FunctionMapEntry>>(sourceCodeUrl => _functionMapGenerator.GenerateFunctionMap(
|
||||
_sourceCodeProvider.GetSourceCode(sourceCodeUrl)));
|
||||
sourceCodeProvider.GetSourceCode(sourceCodeUrl),
|
||||
sourceMapGetter(sourceCodeUrl)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
|
@ -9,6 +10,6 @@ namespace SourcemapToolkit.CallstackDeminifier
|
|||
/// Returns a FunctionMap describing the locations of every funciton in the source code.
|
||||
/// The functions are to be sorted in decreasing order by start position.
|
||||
/// </summary>
|
||||
List<FunctionMapEntry> GenerateFunctionMap(StreamReader sourceCodeStreamReader);
|
||||
List<FunctionMapEntry> GenerateFunctionMap(StreamReader sourceCodeStreamReader, SourceMap sourceMap);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
/// <summary>
|
||||
/// This class only deminfies the method name in a stack frame. It does not depend on having a source map available during runtime.
|
||||
/// </summary>
|
||||
internal class SimpleStackFrameDeminifier : IStackFrameDeminifier
|
||||
{
|
||||
protected readonly IFunctionMapConsumer _functionMapConsumer;
|
||||
protected readonly IFunctionMapStore _functionMapStore;
|
||||
|
||||
public SimpleStackFrameDeminifier(IFunctionMapStore functionMapStore, IFunctionMapConsumer functionMapConsumer)
|
||||
{
|
||||
_functionMapStore = functionMapStore;
|
||||
_functionMapConsumer = functionMapConsumer;
|
||||
}
|
||||
/// <summary>
|
||||
/// This method will deminify the method name of a single stack from from a minified stack trace.
|
||||
/// </summary>
|
||||
public virtual StackFrame DeminifyStackFrame(StackFrame stackFrame)
|
||||
{
|
||||
if (stackFrame == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stackFrame));
|
||||
}
|
||||
|
||||
FunctionMapEntry wrappingFunction = null;
|
||||
|
||||
// This code deminifies the stack frame by finding the wrapping function in
|
||||
// the generated code and then using the source map to find the name and
|
||||
// and original source location.
|
||||
List<FunctionMapEntry> functionMap = _functionMapStore.GetFunctionMapForSourceCode(stackFrame.FilePath);
|
||||
if (functionMap != null)
|
||||
{
|
||||
wrappingFunction =
|
||||
_functionMapConsumer.GetWrappingFunctionForSourceLocation(stackFrame.SourcePosition, functionMap);
|
||||
}
|
||||
|
||||
return new StackFrame {MethodName = wrappingFunction?.DeminfifiedMethodName};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,10 +65,12 @@
|
|||
<Compile Include="IStackFrameDeminifier.cs" />
|
||||
<Compile Include="IStackTraceParser.cs" />
|
||||
<Compile Include="KeyValueCache.cs" />
|
||||
<Compile Include="SimpleStackFrameDeminifier.cs" />
|
||||
<Compile Include="SourceMapStore.cs" />
|
||||
<Compile Include="StackFrame.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StackFrameDeminifier.cs" />
|
||||
<Compile Include="StackTraceDeminfierFactory.cs" />
|
||||
<Compile Include="StackTraceDeminifier.cs" />
|
||||
<Compile Include="StackTraceParser.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,94 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Class responsible for deminifying a single stack frame in a minified stack trace.
|
||||
/// This method of deminification relies on a source map being available at runtime.
|
||||
/// Since source maps take up a large amount of memory, this class consumes considerably
|
||||
/// more memory than SimpleStackFrame Deminifier during runtime.
|
||||
/// </summary>
|
||||
internal class StackFrameDeminifier : IStackFrameDeminifier
|
||||
internal class StackFrameDeminifier : SimpleStackFrameDeminifier
|
||||
{
|
||||
private readonly IFunctionMapConsumer _functionMapConsumer;
|
||||
private readonly IFunctionMapStore _functionMapStore;
|
||||
private readonly ISourceMapStore _sourceMapStore;
|
||||
|
||||
public StackFrameDeminifier(ISourceMapStore sourceMapStore, IFunctionMapStore functionMapStore, IFunctionMapConsumer functionMapConsumer)
|
||||
public StackFrameDeminifier(ISourceMapStore sourceMapStore, IFunctionMapStore functionMapStore, IFunctionMapConsumer functionMapConsumer) : base (functionMapStore, functionMapConsumer)
|
||||
{
|
||||
_functionMapStore = functionMapStore;
|
||||
_sourceMapStore = sourceMapStore;
|
||||
_functionMapConsumer = functionMapConsumer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will deminify a single stack from from a minified stack trace.
|
||||
/// </summary>
|
||||
/// <returns>Returns a stack trace that has been translated to a best guess of the original source code. Any of the fields in the stack frame may be null</returns>
|
||||
public StackFrame DeminifyStackFrame(StackFrame stackFrame)
|
||||
public override StackFrame DeminifyStackFrame(StackFrame stackFrame)
|
||||
{
|
||||
if (stackFrame == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stackFrame));
|
||||
}
|
||||
|
||||
FunctionMapEntry wrappingFunction = null;
|
||||
SourceMap sourceMap = _sourceMapStore.GetSourceMapForUrl(stackFrame.FilePath);
|
||||
SourcePosition generatedSourcePosition = stackFrame.SourcePosition;
|
||||
|
||||
// This code deminifies the stack frame by finding the wrapping function in
|
||||
// the generated code and then using the source map to find the name and
|
||||
// and original source location.
|
||||
List<FunctionMapEntry> functionMap = _functionMapStore.GetFunctionMapForSourceCode(stackFrame.FilePath);
|
||||
if (functionMap != null)
|
||||
{
|
||||
wrappingFunction =
|
||||
_functionMapConsumer.GetWrappingFunctionForSourceLocation(stackFrame.SourcePosition, functionMap);
|
||||
}
|
||||
|
||||
return ExtractFrameInformationFromSourceMap(wrappingFunction, sourceMap, stackFrame.SourcePosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the information necessary for a deminified stack frame from the relevant source map.
|
||||
/// </summary>
|
||||
/// <param name="wrappingFunction">The function that wraps the current stack frame location</param>
|
||||
/// <param name="sourceMap">The relevant source map for this generated code</param>
|
||||
/// <param name="generatedSourcePosition">The location that should be translated to original source code location in the deminified stack frame.</param>
|
||||
/// <returns>Returns a StackFrame object with best guess values for each property. Any of the properties may be null if no match was found.</returns>
|
||||
internal static StackFrame ExtractFrameInformationFromSourceMap(FunctionMapEntry wrappingFunction, SourceMap sourceMap, SourcePosition generatedSourcePosition)
|
||||
{
|
||||
StackFrame result = new StackFrame();
|
||||
|
||||
if (wrappingFunction?.Bindings != null && wrappingFunction.Bindings.Count > 0)
|
||||
{
|
||||
string methodName = null;
|
||||
if (wrappingFunction.Bindings.Count == 2)
|
||||
{
|
||||
MappingEntry objectProtoypeMappingEntry =
|
||||
sourceMap?.GetMappingEntryForGeneratedSourcePosition(wrappingFunction.Bindings[0].SourcePosition);
|
||||
|
||||
methodName = objectProtoypeMappingEntry?.OriginalName;
|
||||
}
|
||||
|
||||
MappingEntry mappingEntry =
|
||||
sourceMap?.GetMappingEntryForGeneratedSourcePosition(wrappingFunction.Bindings.Last().SourcePosition);
|
||||
|
||||
if (mappingEntry != null)
|
||||
{
|
||||
if (mappingEntry.OriginalName != null)
|
||||
{
|
||||
if (methodName != null)
|
||||
{
|
||||
methodName = methodName + "." + mappingEntry.OriginalName;
|
||||
}
|
||||
else
|
||||
{
|
||||
methodName = mappingEntry.OriginalName;
|
||||
}
|
||||
}
|
||||
result.MethodName = methodName;
|
||||
}
|
||||
}
|
||||
StackFrame result = base.DeminifyStackFrame(stackFrame);
|
||||
|
||||
MappingEntry generatedSourcePositionMappingEntry = sourceMap?.GetMappingEntryForGeneratedSourcePosition(generatedSourcePosition);
|
||||
result.FilePath = generatedSourcePositionMappingEntry?.OriginalFileName;
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
public class StackTraceDeminfierFactory
|
||||
{
|
||||
private static void ValidateArguments(ISourceMapProvider sourceMapProvider, ISourceCodeProvider generatedCodeProvider)
|
||||
{
|
||||
if (sourceMapProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceMapProvider));
|
||||
}
|
||||
|
||||
if (generatedCodeProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(generatedCodeProvider));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a StackTraceDeminifier with full capabilities. StackTrace deminifiers created with this method will keep source maps cached, and thus use significantly more memory during runtime than the ones generated with GetMethodNameOnlyStackTraceDeminfier.
|
||||
/// </summary>
|
||||
/// <param name="sourceMapProvider">Consumers of the API should implement this interface, which provides the source map for a given JavaScript file. Throws ArgumentNullException if the parameter is set to null.</param>
|
||||
/// <param name="generatedCodeProvider">Consumers of the API should implement this interface, which provides the contents of a JavaScript file. Throws ArgumentNullException if the parameter is set to null.</param>
|
||||
public static StackTraceDeminifier GetStackTraceDeminfier(ISourceMapProvider sourceMapProvider, ISourceCodeProvider generatedCodeProvider)
|
||||
{
|
||||
ValidateArguments(sourceMapProvider, generatedCodeProvider);
|
||||
|
||||
ISourceMapStore sourceMapStore = new SourceMapStore(sourceMapProvider);
|
||||
IStackFrameDeminifier stackFrameDeminifier = new StackFrameDeminifier(sourceMapStore,
|
||||
new FunctionMapStore(generatedCodeProvider, sourceMapStore.GetSourceMapForUrl), new FunctionMapConsumer());
|
||||
|
||||
IStackTraceParser stackTraceParser = new StackTraceParser();
|
||||
|
||||
return new StackTraceDeminifier(stackFrameDeminifier, stackTraceParser);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a StackTraceDeminifier that only deminifies the method names. StackTrace deminifiers created with this method will use significantly less memory during runtime than the
|
||||
/// </summary>
|
||||
/// <param name="sourceMapProvider">Consumers of the API should implement this interface, which provides the source map for a given JavaScript file. Throws ArgumentNullException if the parameter is set to null.</param>
|
||||
/// <param name="generatedCodeProvider">Consumers of the API should implement this interface, which provides the contents of a JavaScript file. Throws ArgumentNullException if the parameter is set to null.</param>
|
||||
public static StackTraceDeminifier GetMethodNameOnlyStackTraceDeminfier(ISourceMapProvider sourceMapProvider, ISourceCodeProvider generatedCodeProvider)
|
||||
{
|
||||
ValidateArguments(sourceMapProvider, generatedCodeProvider);
|
||||
|
||||
SourceMapParser sourceMapParser = new SourceMapParser();
|
||||
IStackFrameDeminifier stackFrameDeminifier = new SimpleStackFrameDeminifier(new FunctionMapStore(generatedCodeProvider, (url) => sourceMapParser.ParseSourceMap(sourceMapProvider.GetSourceMapContentsForCallstackUrl(url))), new FunctionMapConsumer());
|
||||
|
||||
IStackTraceParser stackTraceParser = new StackTraceParser();
|
||||
|
||||
return new StackTraceDeminifier(stackFrameDeminifier, stackTraceParser);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Public API for parsing and deminifying browser stack traces.
|
||||
/// This class is responsible for parsing a callstack string into
|
||||
/// a list of StackFrame objects and providing the deminified version
|
||||
/// of the stack frame.
|
||||
/// </summary>
|
||||
public class StackTraceDeminifier
|
||||
{
|
||||
private readonly IStackFrameDeminifier _stackFrameDeminifier;
|
||||
private readonly IStackTraceParser _stackTraceParser;
|
||||
|
||||
/// <summary>
|
||||
/// This class is responsible for parsing a callstack string into
|
||||
/// a list of StackFrame objects and providing the deminified version
|
||||
/// of the stack frame.
|
||||
/// </summary>
|
||||
/// <param name="sourceMapProvider">Consumers of the API should implement this interface, which provides the source map for a given JavaScript file. Throws ArgumentNullException if the parameter is set to null.</param>
|
||||
/// <param name="generatedCodeProvider">Consumers of the API should implement this interface, which provides the contents of a JavaScript file. Throws ArgumentNullException if the parameter is set to null.</param>
|
||||
public StackTraceDeminifier(ISourceMapProvider sourceMapProvider, ISourceCodeProvider generatedCodeProvider)
|
||||
: this(new StackFrameDeminifier(new SourceMapStore(sourceMapProvider),
|
||||
new FunctionMapStore(generatedCodeProvider), new FunctionMapConsumer()), new StackTraceParser())
|
||||
{
|
||||
if (sourceMapProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sourceMapProvider));
|
||||
}
|
||||
|
||||
if (generatedCodeProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(generatedCodeProvider));
|
||||
}
|
||||
}
|
||||
|
||||
internal StackTraceDeminifier(IStackFrameDeminifier stackFrameDeminifier, IStackTraceParser stackTraceParser)
|
||||
{
|
||||
_stackFrameDeminifier = stackFrameDeminifier;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SourcemapToolkit.SourcemapParser.UnitTests;
|
||||
using Rhino.Mocks;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
||||
{
|
||||
|
@ -9,41 +11,56 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
public class FunctionMapGeneratorUnitTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_NullInput_ReturnsNull()
|
||||
public void GenerateFunctionMap_NullSourceMap_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(null);
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode), null);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(functionMap);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void ParseSourceCode_NullInput_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(null);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(functionMap);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_NoFunctionsInSource_EmptyFunctionList()
|
||||
public void ParseSourceCode_NoFunctionsInSource_EmptyFunctionList()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "bar();";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(0, functionMap.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_SingleLineFunctionInSource_CorrectZeroBasedColumnNumbers()
|
||||
public void ParseSourceCode_SingleLineFunctionInSource_CorrectZeroBasedColumnNumbers()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "function foo(){bar();}";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, functionMap.Count);
|
||||
|
@ -57,15 +74,15 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_MultiLineFunctionInSource_CorrectColumnAndZeroBasedLineNumbers()
|
||||
public void ParseSourceCode_MultiLineFunctionInSource_CorrectColumnAndZeroBasedLineNumbers()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "function foo()" + Environment.NewLine + "{" + Environment.NewLine + "bar();" +
|
||||
Environment.NewLine + "}";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, functionMap.Count);
|
||||
|
@ -79,14 +96,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_TwoSingleLineFunctions_TwoFunctionMapEntries()
|
||||
public void ParseSourceCode_TwoSingleLineFunctions_TwoFunctionMapEntries()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "function foo(){bar();}function bar(){baz();}";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -109,14 +126,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_TwoNestedSingleLineFunctions_TwoFunctionMapEntries()
|
||||
public void ParseSourceCode_TwoNestedSingleLineFunctions_TwoFunctionMapEntries()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "function foo(){function bar(){baz();}}";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -139,14 +156,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_FunctionAssignedToVariable_FunctionMapEntryGenerated()
|
||||
public void ParseSourceCode_FunctionAssignedToVariable_FunctionMapEntryGenerated()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){bar();}";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, functionMap.Count);
|
||||
|
@ -161,14 +178,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_StaticMethod_FunctionMapEntryGenerated()
|
||||
public void ParseSourceCode_StaticMethod_FunctionMapEntryGenerated()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){};foo.bar = function() { baz(); }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -191,14 +208,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_InstanceMethod_FunctionMapEntryGenerated()
|
||||
public void ParseSourceCode_InstanceMethod_FunctionMapEntryGenerated()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){} foo.prototype.bar = function () { baz(); }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -221,14 +238,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_InstanceMethodInObjectInitializer_FunctionMapEntryGenerated()
|
||||
public void ParseSourceCode_InstanceMethodInObjectInitializer_FunctionMapEntryGenerated()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){} foo.prototype = { bar: function () { baz(); } }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -254,14 +271,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_FunctionAssignedToVariableAndHasName_FunctionMapEntryGeneratedForVariableName()
|
||||
public void ParseSourceCode_FunctionAssignedToVariableAndHasName_FunctionMapEntryGeneratedForVariableName()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function myCoolFunctionName(){ bar(); }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, functionMap.Count);
|
||||
|
@ -276,14 +293,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_StaticMethodAndFunctionHasName_FunctionMapEntryGeneratedForPropertyName()
|
||||
public void ParseSourceCode_StaticMethodAndFunctionHasName_FunctionMapEntryGeneratedForPropertyName()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){};foo.bar = function myCoolFunctionName() { baz(); }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -306,14 +323,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_InstanceMethodAndFunctionHasName_FunctionMapEntryGeneratedForObjectPrototype()
|
||||
public void ParseSourceCode_InstanceMethodAndFunctionHasName_FunctionMapEntryGeneratedForObjectPrototype()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){} foo.prototype.bar = function myCoolFunctionName() { baz(); } }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -336,14 +353,14 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateFunctionMap_InstanceMethodWithObjectInitializerAndFunctionHasName_FunctionMapEntryGeneratedForObjectPrototype()
|
||||
public void ParseSourceCode_InstanceMethodWithObjectInitializerAndFunctionHasName_FunctionMapEntryGeneratedForObjectPrototype()
|
||||
{
|
||||
// Arrange
|
||||
IFunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
FunctionMapGenerator functionMapGenerator = new FunctionMapGenerator();
|
||||
string sourceCode = "var foo = function(){} foo.prototype = { bar: function myCoolFunctionName() { baz(); } }";
|
||||
|
||||
// Act
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.GenerateFunctionMap(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
List<FunctionMapEntry> functionMap = functionMapGenerator.ParseSourceCode(UnitTestUtils.StreamReaderFromString(sourceCode));
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, functionMap.Count);
|
||||
|
@ -367,5 +384,128 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
Assert.AreEqual(20, functionMap[1].StartSourcePosition.ZeroBasedColumnNumber);
|
||||
Assert.AreEqual(22, functionMap[1].EndSourcePosition.ZeroBasedColumnNumber);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetDeminifiedMethodNameFromSourceMap_NoBinding_ReturnNullMethodName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry();
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
|
||||
// Act
|
||||
string result = FunctionMapGenerator.GetDeminifiedMethodNameFromSourceMap(functionMapEntry, sourceMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(result);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetDeminifiedMethodNameFromSourceMap_HasSingleBindingNoMatchingMapping_ReturnNullMethodName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry
|
||||
{
|
||||
Bindings =
|
||||
new List<BindingInformation>
|
||||
{
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 20, ZeroBasedColumnNumber = 15}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(x => x.GetMappingEntryForGeneratedSourcePosition(Arg<SourcePosition>.Is.Anything)).Return(null);
|
||||
|
||||
// Act
|
||||
string result = FunctionMapGenerator.GetDeminifiedMethodNameFromSourceMap(functionMapEntry, sourceMap);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(result);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetDeminifiedMethodNameFromSourceMap_HasSingleBindingMatchingMapping_ReturnsMethodName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry
|
||||
{
|
||||
Bindings =
|
||||
new List<BindingInformation>
|
||||
{
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 5, ZeroBasedColumnNumber = 8}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(
|
||||
x =>
|
||||
x.GetMappingEntryForGeneratedSourcePosition(
|
||||
Arg<SourcePosition>.Matches(y => y.ZeroBasedLineNumber == 5 && y.ZeroBasedColumnNumber == 8)))
|
||||
.Return(new MappingEntry
|
||||
{
|
||||
OriginalName = "foo",
|
||||
});
|
||||
|
||||
// Act
|
||||
string result = FunctionMapGenerator.GetDeminifiedMethodNameFromSourceMap(functionMapEntry, sourceMap);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("foo", result);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetDeminifiedMethodNameFromSourceMap_MatchingMappingMultipleBindings_ReturnsMethodNameWithFullBinding()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry
|
||||
{
|
||||
Bindings =
|
||||
new List<BindingInformation>
|
||||
{
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 5, ZeroBasedColumnNumber = 5}
|
||||
},
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 20, ZeroBasedColumnNumber = 10}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(
|
||||
x =>
|
||||
x.GetMappingEntryForGeneratedSourcePosition(
|
||||
Arg<SourcePosition>.Matches(y => y.ZeroBasedLineNumber == 5 && y.ZeroBasedColumnNumber == 5)))
|
||||
.Return(new MappingEntry
|
||||
{
|
||||
OriginalName = "bar"
|
||||
});
|
||||
|
||||
sourceMap.Stub(
|
||||
x =>
|
||||
x.GetMappingEntryForGeneratedSourcePosition(
|
||||
Arg<SourcePosition>.Matches(y => y.ZeroBasedLineNumber == 20 && y.ZeroBasedColumnNumber == 10)))
|
||||
.Return(new MappingEntry
|
||||
{
|
||||
OriginalName = "baz",
|
||||
});
|
||||
|
||||
// Act
|
||||
string result = FunctionMapGenerator.GetDeminifiedMethodNameFromSourceMap(functionMapEntry, sourceMap);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("bar.baz", result);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,7 +70,6 @@
|
|||
<Compile Include="StackTraceDeminifierUnitTests.cs" />
|
||||
<Compile Include="StackTraceParserUnitTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StackFrameDeminifierUnitTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\SourceMapToolkit.CallstackDeminifier\SourcemapToolkit.CallstackDeminifier.csproj">
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Rhino.Mocks;
|
||||
using SourcemapToolkit.SourcemapParser;
|
||||
|
||||
namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
||||
{
|
||||
[TestClass]
|
||||
public class StackFrameDeminifierUnitTests
|
||||
{
|
||||
private IStackFrameDeminifier GetStackFrameDeminifierWithMockDependencies(ISourceMapStore sourceMapStore = null, IFunctionMapStore functionMapStore = null, IFunctionMapConsumer functionMapConsumer = null)
|
||||
{
|
||||
if (sourceMapStore == null)
|
||||
{
|
||||
sourceMapStore = MockRepository.GenerateStrictMock<ISourceMapStore>();
|
||||
}
|
||||
|
||||
if (functionMapStore == null)
|
||||
{
|
||||
functionMapStore = MockRepository.GenerateStrictMock<IFunctionMapStore>();
|
||||
}
|
||||
|
||||
if (functionMapConsumer == null)
|
||||
{
|
||||
functionMapConsumer = MockRepository.GenerateStrictMock<IFunctionMapConsumer>();
|
||||
}
|
||||
|
||||
return new StackFrameDeminifier(sourceMapStore, functionMapStore, functionMapConsumer);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void DeminifyStackFrame_NullInputStackFrame_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
IStackFrameDeminifier stackFrameDeminifier = GetStackFrameDeminifierWithMockDependencies();
|
||||
StackFrame stackFrame = null;
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = stackFrameDeminifier.DeminifyStackFrame(stackFrame);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ExtractFrameInformationFromSourceMap_NullInputs_DoesNotThrowException()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = null;
|
||||
SourceMap sourceMap = null;
|
||||
SourcePosition generatedSourcePosition = null;
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = StackFrameDeminifier.ExtractFrameInformationFromSourceMap(functionMapEntry, sourceMap, generatedSourcePosition);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(deminifiedStackFrame.MethodName);
|
||||
Assert.IsNull(deminifiedStackFrame.SourcePosition);
|
||||
Assert.IsNull(deminifiedStackFrame.FilePath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ExtractFrameInformationFromSourceMap_NoBinding_ReturnNullMethodName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry();
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
SourcePosition generatedSourcePosition = new SourcePosition();
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = StackFrameDeminifier.ExtractFrameInformationFromSourceMap(functionMapEntry, sourceMap, generatedSourcePosition);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(deminifiedStackFrame.MethodName);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ExtractFrameInformationFromSourceMap_HasSingleBindingNoMatchingMapping_ReturnNullMethodName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry
|
||||
{
|
||||
Bindings =
|
||||
new List<BindingInformation>
|
||||
{
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 20, ZeroBasedColumnNumber = 15}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(x => x.GetMappingEntryForGeneratedSourcePosition(Arg<SourcePosition>.Is.Anything)).Return(null);
|
||||
|
||||
SourcePosition generatedSourcePosition = new SourcePosition();
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = StackFrameDeminifier.ExtractFrameInformationFromSourceMap(functionMapEntry, sourceMap, generatedSourcePosition);
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(deminifiedStackFrame.MethodName);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ExtractFrameInformationFromSourceMap_HasSingleBindingMatchingMapping_ReturnsStackFrameWithMethodName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry
|
||||
{
|
||||
Bindings =
|
||||
new List<BindingInformation>
|
||||
{
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 5, ZeroBasedColumnNumber = 8}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SourcePosition generatedSourcePosition = new SourcePosition
|
||||
{
|
||||
ZeroBasedColumnNumber = 25,
|
||||
ZeroBasedLineNumber = 85
|
||||
};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(
|
||||
x =>
|
||||
x.GetMappingEntryForGeneratedSourcePosition(
|
||||
Arg<SourcePosition>.Matches(y => y.ZeroBasedLineNumber == 5 && y.ZeroBasedColumnNumber == 8)))
|
||||
.Return(new MappingEntry
|
||||
{
|
||||
OriginalName = "foo",
|
||||
});
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = StackFrameDeminifier.ExtractFrameInformationFromSourceMap(functionMapEntry, sourceMap, generatedSourcePosition);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("foo", deminifiedStackFrame.MethodName);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ExtractFrameInformationFromSourceMap_MatchingMappingMultipleBindings_ReturnsStackFrameWithFullBinding()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = new FunctionMapEntry
|
||||
{
|
||||
Bindings =
|
||||
new List<BindingInformation>
|
||||
{
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 5, ZeroBasedColumnNumber = 5}
|
||||
},
|
||||
new BindingInformation
|
||||
{
|
||||
SourcePosition = new SourcePosition {ZeroBasedLineNumber = 20, ZeroBasedColumnNumber = 10}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SourcePosition generatedSourcePosition = new SourcePosition {ZeroBasedColumnNumber = 39, ZeroBasedLineNumber = 31};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(
|
||||
x =>
|
||||
x.GetMappingEntryForGeneratedSourcePosition(
|
||||
Arg<SourcePosition>.Matches(y => y.ZeroBasedLineNumber == 5 && y.ZeroBasedColumnNumber == 5)))
|
||||
.Return(new MappingEntry
|
||||
{
|
||||
OriginalName = "bar"
|
||||
});
|
||||
|
||||
sourceMap.Stub(
|
||||
x =>
|
||||
x.GetMappingEntryForGeneratedSourcePosition(
|
||||
Arg<SourcePosition>.Matches(y => y.ZeroBasedLineNumber == 20 && y.ZeroBasedColumnNumber == 10)))
|
||||
.Return(new MappingEntry
|
||||
{
|
||||
OriginalName = "baz",
|
||||
});
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = StackFrameDeminifier.ExtractFrameInformationFromSourceMap(functionMapEntry, sourceMap, generatedSourcePosition);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual("bar.baz", deminifiedStackFrame.MethodName);
|
||||
sourceMap.VerifyAllExpectations();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ExtractFrameInformationFromSourceMap_HasMatchingGeneratedPositionMapping_ReturnsStackFrameWithSourcePositionAndFileName()
|
||||
{
|
||||
// Arrange
|
||||
FunctionMapEntry functionMapEntry = null;
|
||||
SourcePosition generatedSourcePosition = new SourcePosition
|
||||
{
|
||||
ZeroBasedColumnNumber = 25,
|
||||
ZeroBasedLineNumber = 85
|
||||
};
|
||||
|
||||
SourceMap sourceMap = MockRepository.GenerateStub<SourceMap>();
|
||||
sourceMap.Stub(x => x.GetMappingEntryForGeneratedSourcePosition(generatedSourcePosition)).Return(new MappingEntry
|
||||
{
|
||||
OriginalSourcePosition = new SourcePosition { ZeroBasedColumnNumber = 10, ZeroBasedLineNumber = 20 }
|
||||
});
|
||||
|
||||
// Act
|
||||
StackFrame deminifiedStackFrame = StackFrameDeminifier.ExtractFrameInformationFromSourceMap(functionMapEntry, sourceMap, generatedSourcePosition);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(10, deminifiedStackFrame.SourcePosition.ZeroBasedColumnNumber);
|
||||
Assert.AreEqual(20, deminifiedStackFrame.SourcePosition.ZeroBasedLineNumber);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
ISourceCodeProvider sourceCodeProvider = MockRepository.GenerateStrictMock<ISourceCodeProvider>();
|
||||
sourceCodeProvider.Stub(x => x.GetSourceCode("http://localhost:11323/crashcauser.js")).Return(UnitTestUtils.StreamReaderFromString(GeneratedCodeString));
|
||||
|
||||
return new StackTraceDeminifier(sourceMapProvider, sourceCodeProvider);
|
||||
return StackTraceDeminfierFactory.GetStackTraceDeminfier(sourceMapProvider, sourceCodeProvider);
|
||||
}
|
||||
|
||||
private void ValidateDeminifyStackTraceResults(DeminifyStackTraceResult results)
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
ISourceCodeProvider sourceCodeProvider = MockRepository.GenerateStrictMock<ISourceCodeProvider>();
|
||||
sourceCodeProvider.Stub(x => x.GetSourceCode("http://localhost:11323/crashcauser.min.js")).Return(UnitTestUtils.StreamReaderFromString(GeneratedCodeString));
|
||||
|
||||
return new StackTraceDeminifier(sourceMapProvider, sourceCodeProvider);
|
||||
}
|
||||
return StackTraceDeminfierFactory.GetStackTraceDeminfier(sourceMapProvider, sourceCodeProvider);
|
||||
}
|
||||
|
||||
private static void ValidateDeminifyStackTraceResults(DeminifyStackTraceResult results)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Rhino.Mocks;
|
||||
|
||||
|
@ -8,30 +7,6 @@ namespace SourcemapToolkit.CallstackDeminifier.UnitTests
|
|||
[TestClass]
|
||||
public class StackTraceDeminifierUnitTests
|
||||
{
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void StackTraceDeminifier_NullSourceMapProvider_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
ISourceCodeProvider sourceCodeProvider = MockRepository.GenerateStrictMock<ISourceCodeProvider>();
|
||||
ISourceMapProvider sourceMapProvider = null;
|
||||
|
||||
// Act
|
||||
StackTraceDeminifier stackTraceDeminifier = new StackTraceDeminifier(sourceMapProvider, sourceCodeProvider);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void StackTraceDeminifier_NullSourceCodeProvider_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
ISourceCodeProvider sourceCodeProvider = null;
|
||||
ISourceMapProvider sourceMapProvider = MockRepository.GenerateStrictMock<ISourceMapProvider>();
|
||||
|
||||
// Act
|
||||
StackTraceDeminifier stackTraceDeminifier = new StackTraceDeminifier(sourceMapProvider, sourceCodeProvider);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DeminifyStackTrace_UnableToParseStackTraceString_ReturnsEmptyList()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче