Skip to content
This repository has been archived by the owner on Nov 15, 2021. It is now read-only.

Commit

Permalink
Merge pull request #489 from ddur/master
Browse files Browse the repository at this point in the history
Feature+ Matching assembly by path #364
  • Loading branch information
ddur committed Jan 17, 2016
2 parents 283e67f + a5cb9d7 commit 2458590
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 80 deletions.
6 changes: 3 additions & 3 deletions main/OpenCover.Framework/Communication/MessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private int HandleGetSequencePointsMessage(IntPtr pinnedMemory, IManagedCommunic
{
var request = _marshalWrapper.PtrToStructure<MSG_GetSequencePoints_Request>(pinnedMemory);
InstrumentationPoint[] origPoints;
_profilerCommunication.GetSequencePoints(request.processName, request.modulePath, request.assemblyName,
_profilerCommunication.GetSequencePoints(request.processPath, request.modulePath, request.assemblyName,
request.functionToken, out origPoints);
var num = origPoints.Maybe(o => o.Length);

Expand Down Expand Up @@ -169,7 +169,7 @@ private int HandleGetBranchPointsMessage(IntPtr pinnedMemory, IManagedCommunicat
{
var request = _marshalWrapper.PtrToStructure<MSG_GetBranchPoints_Request>(pinnedMemory);
BranchPoint[] origPoints;
_profilerCommunication.GetBranchPoints(request.processName, request.modulePath, request.assemblyName,
_profilerCommunication.GetBranchPoints(request.processPath, request.modulePath, request.assemblyName,
request.functionToken, out origPoints);
var num = origPoints.Maybe(o => o.Length);

Expand Down Expand Up @@ -290,7 +290,7 @@ private int HandleTrackAssemblyMessage(IntPtr pinnedMemory)
try
{
var request = _marshalWrapper.PtrToStructure<MSG_TrackAssembly_Request>(pinnedMemory);
response.track = _profilerCommunication.TrackAssembly(request.processName, request.modulePath, request.assemblyName);
response.track = _profilerCommunication.TrackAssembly(request.processPath, request.modulePath, request.assemblyName);
}
catch (Exception ex)
{
Expand Down
6 changes: 3 additions & 3 deletions main/OpenCover.Framework/Communication/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public struct MSG_TrackAssembly_Request
/// The path to the process
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
public string processName;
public string processPath;

/// <summary>
/// The path to the module/assembly
Expand Down Expand Up @@ -144,7 +144,7 @@ public struct MSG_GetSequencePoints_Request
/// The path to the process
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
public string processName;
public string processPath;

/// <summary>
/// The path to the module hosting the emthod
Expand Down Expand Up @@ -214,7 +214,7 @@ public struct MSG_GetBranchPoints_Request
/// The path to the process
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
public string processName;
public string processPath;

/// <summary>
/// The path to the module hosting the emthod
Expand Down
88 changes: 50 additions & 38 deletions main/OpenCover.Framework/Filter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,21 @@ public Filter(bool useRegexFilters = false)
/// Decides whether an assembly should be included in the instrumentation
/// </summary>
/// <param name="processPath">The path-name of the process being profiled</param>
/// <param name="assemblyName">the name of the assembly under profile</param>
/// <param name="assemblyPath">The path-name of the assembly under profile</param>
/// <remarks>All assemblies matching either the inclusion or exclusion filter should be included
/// as it is the class that is being filtered within these unless the class filter is *</remarks>
public bool UseAssembly(string processPath, string assemblyName)
public bool UseAssembly(string processPath, string assemblyPath)
{
var processName = string.Empty;
if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException
processName = Path.GetFileNameWithoutExtension(processPath);
}
var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName);
var assemblyName = string.Empty;
if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException
assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
}
var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath);
if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); }
if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((!string.IsNullOrEmpty(processName) && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath))))
{
return false;
Expand All @@ -73,7 +78,8 @@ public bool UseAssembly(string processPath, string assemblyName)
return true;
}

var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName);
var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath);
if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); }
if (matchingInclusionFilters.Any())
{
return true;
Expand All @@ -86,21 +92,26 @@ public bool UseAssembly(string processPath, string assemblyName)
/// Determine if an [assemblyname]classname pair matches the current Exclusion or Inclusion filters
/// </summary>
/// <param name="processPath">The path-name of the process</param>
/// <param name="assemblyName">the name of the assembly under profile</param>
/// <param name="assemblyPath">the name of the assembly under profile</param>
/// <param name="className">the name of the class under profile</param>
/// <returns>false - if pair matches the exclusion filter or matches no filters, true - if pair matches in the inclusion filter</returns>
public bool InstrumentClass(string processPath, string assemblyName, string className)
public bool InstrumentClass(string processPath, string assemblyPath, string className)
{
if (string.IsNullOrEmpty(processPath) || string.IsNullOrEmpty(assemblyName) || string.IsNullOrEmpty(className))
if (string.IsNullOrEmpty(processPath) || string.IsNullOrEmpty(assemblyPath) || string.IsNullOrEmpty(className))
{
return false;
}

var processName = string.Empty;
if (processPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException
processName = Path.GetFileNameWithoutExtension(processPath);
processName = Path.GetFileNameWithoutExtension(processPath); // can return null
}
var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName);
var assemblyName = string.Empty;
if (assemblyPath.IndexOfAny(Path.GetInvalidPathChars()) < 0) { // avoids ArgumentException
assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); // can return null
}
var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath);
if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingExclusionFilters.AddRange (ExclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); }
if (matchingExclusionFilters.Any(exclusionFilter => exclusionFilter.ClassName == ".*" && ((!string.IsNullOrEmpty(processName) && exclusionFilter.IsMatchingProcessName(processName)) || exclusionFilter.IsMatchingProcessName(processPath))))
{
return false;
Expand All @@ -113,7 +124,8 @@ public bool InstrumentClass(string processPath, string assemblyName, string clas
return false;
}

var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName);
var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyPath);
if (!string.IsNullOrEmpty(assemblyName) && assemblyName != assemblyPath) { matchingInclusionFilters.AddRange (InclusionFilters.GetMatchingFiltersForAssemblyName(assemblyName)); }
if (matchingInclusionFilters.Any(inclusionFilter => inclusionFilter.IsMatchingClassName(className)))
{
return true;
Expand All @@ -126,38 +138,38 @@ public bool InstrumentClass(string processPath, string assemblyName, string clas
/// <summary>
/// Determine if an [assemblyname]classname pair matches the current Exclusion or Inclusion filters
/// </summary>
/// <param name="assemblyName">the name of the assembly under profile</param>
/// <param name="className">the name of the class under profile</param>
/// <param name="assemblyPath">The path-name of the assembly under profile</param>
/// <param name="className">The name of the class under profile</param>
/// <returns>false - if pair matches the exclusion filter or matches no filters, true - if pair matches in the inclusion filter</returns>
public bool InstrumentClass(string assemblyName, string className)
public bool InstrumentClass(string assemblyPath, string className)
{
return InstrumentClass(Guid.NewGuid().ToString(), assemblyName, className);
return InstrumentClass(Guid.NewGuid().ToString(), assemblyPath, className);
}

/// <summary>
/// Add a filter
/// </summary>
/// <param name="assemblyClassName">A filter is of the format (+ or -)[assemblyName]className, wildcards are allowed. <br/>
/// <param name="processAssemblyClassFilter">Filter is of the format (+ or -)&lt;processFilter&gt;[assemblyFilter]classFilter, wildcards are allowed. <br/>
/// i.e. -[mscorlib], -[System.*]*, +[App.*]*, +[*]*
/// </param>
public void AddFilter(string assemblyClassName)
public void AddFilter(string processAssemblyClassFilter)
{
string assemblyName;
string className;
string processName;
string _assemblyFilter;
string _classFilter;
string _processFilter;
FilterType filterType;
GetAssemblyClassName(assemblyClassName, RegExFilters, out filterType, out assemblyName, out className, out processName);
GetAssemblyClassName(processAssemblyClassFilter, RegExFilters, out filterType, out _assemblyFilter, out _classFilter, out _processFilter);

try
{
if (!RegExFilters)
{
processName = (string.IsNullOrEmpty(processName) ? "*" : processName).ValidateAndEscape("<>|\""); // Path.GetInvalidPathChars except *?
assemblyName = assemblyName.ValidateAndEscape();
className = className.ValidateAndEscape();
_processFilter = (string.IsNullOrEmpty(_processFilter) ? "*" : _processFilter).ValidateAndEscape("<>|\""); // Path.GetInvalidPathChars except *?
_assemblyFilter = _assemblyFilter.ValidateAndEscape();
_classFilter = _classFilter.ValidateAndEscape();
}

var filter = new AssemblyAndClassFilter(processName, assemblyName, className);
var filter = new AssemblyAndClassFilter(_processFilter, _assemblyFilter, _classFilter);
if (filterType == FilterType.Inclusion)
InclusionFilters.Add(filter);

Expand All @@ -166,34 +178,34 @@ public void AddFilter(string assemblyClassName)
}
catch (Exception)
{
HandleInvalidFilterFormat(assemblyClassName);
HandleInvalidFilterFormat(processAssemblyClassFilter);
}
}

private static void GetAssemblyClassName(string assemblyClassName, bool useRegEx, out FilterType filterType, out string assemblyName, out string className, out string processName)
private static void GetAssemblyClassName(string processAssemblyClassFilter, bool useRegEx, out FilterType filterType, out string assemblyFilter, out string classFilter, out string processFilter)
{
className = string.Empty;
assemblyName = string.Empty;
processName = string.Empty;
classFilter = string.Empty;
assemblyFilter = string.Empty;
processFilter = string.Empty;
filterType = FilterType.Inclusion;
var regEx = new Regex(@"^(?<type>([+-]))(<(?<process>(.+))>)?(\[(?<assembly>(.+))\])(?<class>(.+))$");
if (useRegEx)
regEx = new Regex(@"^(?<type>([+-]))(<\((?<process>(.+))\)>)?(\[\((?<assembly>(.+))\)\])(\((?<class>(.+))\))$");

var match = regEx.Match(assemblyClassName);
var match = regEx.Match(processAssemblyClassFilter);
if (match.Success)
{
filterType = match.Groups["type"].Value.ParseFilterType();
assemblyName = match.Groups["assembly"].Value;
className = match.Groups["class"].Value;
processName = match.Groups["process"].Value;
assemblyFilter = match.Groups["assembly"].Value;
classFilter = match.Groups["class"].Value;
processFilter = match.Groups["process"].Value;

if (string.IsNullOrWhiteSpace(assemblyName))
HandleInvalidFilterFormat(assemblyClassName);
if (string.IsNullOrWhiteSpace(assemblyFilter))
HandleInvalidFilterFormat(processAssemblyClassFilter);
}
else
{
HandleInvalidFilterFormat(assemblyClassName);
HandleInvalidFilterFormat(processAssemblyClassFilter);
}
}

Expand Down Expand Up @@ -355,7 +367,7 @@ public bool InstrumentProcess(string processPath)
processName = Path.GetFileNameWithoutExtension(processPath);
}
if (ExclusionFilters.Any()) {
var matchingExclusionFilters = new List<AssemblyAndClassFilter>(ExclusionFilters.GetMatchingFiltersForProcessName(processPath));
var matchingExclusionFilters = ExclusionFilters.GetMatchingFiltersForProcessName(processPath);
if (!string.IsNullOrWhiteSpace (processName) && processName != processPath) {
matchingExclusionFilters.AddRange(ExclusionFilters.GetMatchingFiltersForProcessName(processName));
}
Expand All @@ -371,7 +383,7 @@ public bool InstrumentProcess(string processPath)
}

if (InclusionFilters.Any()) {
var matchingInclusionFilters = new List<AssemblyAndClassFilter>(InclusionFilters.GetMatchingFiltersForProcessName(processPath));
var matchingInclusionFilters = InclusionFilters.GetMatchingFiltersForProcessName(processPath);
if (!string.IsNullOrWhiteSpace (processName) && processName != processPath) {
matchingInclusionFilters.AddRange(InclusionFilters.GetMatchingFiltersForProcessName(processName));
}
Expand Down
30 changes: 15 additions & 15 deletions main/OpenCover.Framework/Filtering/AssemblyAndClassFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,38 @@ namespace OpenCover.Framework.Filtering
{
internal class AssemblyAndClassFilter
{
private readonly RegexFilter _processNameFilter;
private readonly RegexFilter _processFilter;

private readonly RegexFilter _assemblyNameFilter;
private readonly RegexFilter _assemblyFilter;

private readonly RegexFilter _classNameFilter;
private readonly RegexFilter _classFilter;

internal string ProcessName { get { return _processNameFilter.FilterExpression; } }
internal string ProcessName { get { return _processFilter.FilterExpression; } }

internal string AssemblyName { get { return _assemblyNameFilter.FilterExpression; } }
internal string AssemblyName { get { return _assemblyFilter.FilterExpression; } }

internal string ClassName { get { return _classNameFilter.FilterExpression; } }
internal string ClassName { get { return _classFilter.FilterExpression; } }

internal AssemblyAndClassFilter(string processName, string assemblyName, string className)
internal AssemblyAndClassFilter(string processFilter, string assemblyFilter, string classFilter)
{
_processNameFilter = new RegexFilter(processName);
_assemblyNameFilter = new RegexFilter(assemblyName);
_classNameFilter = new RegexFilter(className);
_processFilter = new RegexFilter(processFilter);
_assemblyFilter = new RegexFilter(assemblyFilter);
_classFilter = new RegexFilter(classFilter);
}

internal bool IsMatchingProcessName(string processName)
internal bool IsMatchingProcessName(string processPathOrName)
{
return _processNameFilter.IsMatchingExpression(processName);
return _processFilter.IsMatchingExpression(processPathOrName);
}

internal bool IsMatchingAssemblyName(string assemblyName)
internal bool IsMatchingAssemblyName(string assemblyPathOrName)
{
return _assemblyNameFilter.IsMatchingExpression(assemblyName);
return _assemblyFilter.IsMatchingExpression(assemblyPathOrName);
}

internal bool IsMatchingClassName(string className)
{
return _classNameFilter.IsMatchingExpression(className);
return _classFilter.IsMatchingExpression(className);
}
}

Expand Down
9 changes: 9 additions & 0 deletions main/OpenCover.Framework/Filtering/FilterHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ internal static IList<AssemblyAndClassFilter> GetMatchingFiltersForProcessName(t
return matchingFilters;
}

internal static void AddRange<T> (this ICollection<T> collection, IEnumerable<T> range) {
if (collection != null && range != null) {
foreach (var item in range)
{
collection.Add(item);
}
}
}

internal static void AddFilters(this ICollection<RegexFilter> target, IEnumerable<string> filters, bool isRegexFilter)
{
if (filters == null)
Expand Down
Loading

0 comments on commit 2458590

Please sign in to comment.