Skip to content
This repository was archived by the owner on Nov 15, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ReleaseNotes.tmp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Version [[version]]
#376 protect buffer allocation in multithreaded environment (fix)
#335 allow short wait timeout to be configured (feature)

Version 4.6.210 (rc - remove)
#282 exclude by process (feature)
Expand Down
6 changes: 3 additions & 3 deletions main/OpenCover.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static int Main(string[] args)
{
Logger.FatalFormat("An exception occured: {0}", ex.Message);
Logger.FatalFormat("stack: {0}", ex.StackTrace);
Logger.FatalFormat("A report has been sent to the OenCover development team...");
Logger.FatalFormat("A report has been sent to the OpenCover development team...");
}

ReportCrash(ex);
Expand Down Expand Up @@ -109,7 +109,7 @@ private static void ReportCrash(Exception exception)

uploader.SendAnonymousReport(SendRequestState.GetClientLib(), state.GetApplication(), state.GetExceptionDescription(true));
}
catch (Exception ex)
catch (Exception)
{
System.Console.WriteLine("Failed to send crash report :(");
}
Expand Down Expand Up @@ -303,7 +303,7 @@ private static void RunService(CommandLineParser parser, Action<StringDictionary
// Stopping w3svc host
if (parser.Target.ToLower().Equals("w3svc"))
{
logger.InfoFormat("Stopping svchost to clean up environment variables for w3svc", parser.Target);
logger.InfoFormat("Stopping svchost to clean up environment variables for {0}", parser.Target);
if (ServiceEnvironmentManagementEx.IsServiceStartAutomatic(parser.Target))
{
logger.InfoFormat("Please note that the 'w3svc' service may automatically start");
Expand Down
4 changes: 4 additions & 0 deletions main/OpenCover.Framework/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ public void Initialise(IFilter filter,
_container = builder.Build();
}

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority>2</filterpriority>
public void Dispose()
{
if (_container == null) return;
Expand Down
13 changes: 12 additions & 1 deletion main/OpenCover.Framework/CommandLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ public string Usage()
builder.AppendLine(" [-hideskipped:File|Filter|Attribute|MissingPdb|All,[File|Filter|Attribute|MissingPdb|All]]");
builder.AppendLine(" [-log:[Off|Fatal|Error|Warn|Info|Debug|Verbose|All]]");
builder.AppendLine(" [-service[:byname]]");
builder.AppendLine(" [-servicestarttimeout:1m23s");
builder.AppendLine(" [-servicestarttimeout:<minutes+seconds e.g. 1m23s>");
builder.AppendLine(" [-communicationtimeout:<integer, e.g. 10000>");
builder.AppendLine(" [-threshold:<max count>]");
builder.AppendLine(" [-enableperformancecounters]");
builder.AppendLine(" [-skipautoprops]");
Expand Down Expand Up @@ -190,6 +191,11 @@ public void ExtractAndValidateArguments()
ReturnCodeOffset = ExtractValue<int>("returntargetcode", () =>
{ throw new InvalidOperationException("The return target code offset must be an integer"); });
break;
case "communicationtimeout":
CommunicationTimeout = ExtractValue<int>("communicationtimeout", () =>
{ throw new InvalidOperationException(string.Format("The communication timeout must be an integer: {0}", GetArgumentValue("communicationtimeout"))); });
CommunicationTimeout = Math.Max(Math.Min(CommunicationTimeout, 60000), 10000);
break;
case "filter":
Filters = ExtractFilters(GetArgumentValue("filter"));
break;
Expand Down Expand Up @@ -511,6 +517,11 @@ private void ValidateArguments()
/// Instructs the console to print its version and exit
/// </summary>
public bool PrintVersion { get; private set; }

/// <summary>
/// Sets the 'short' timeout between profiler and host (normally 10000ms)
/// </summary>
public int CommunicationTimeout { get; private set; }
}

}
15 changes: 12 additions & 3 deletions main/OpenCover.Framework/Communication/CommunicationManager.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using log4net.Repository.Hierarchy;
using OpenCover.Framework.Manager;
using OpenCover.Framework.Service;

namespace OpenCover.Framework.Communication
{
Expand Down Expand Up @@ -48,6 +45,11 @@ public CommunicationManager(IMessageHandler messageHandler)
_messageHandler = messageHandler;
}

/// <summary>
/// Process a communication related message from a profiler
/// </summary>
/// <param name="mcb"></param>
/// <param name="offloadHandling"></param>
public void HandleCommunicationBlock(IManagedCommunicationBlock mcb, Action<ManagedBufferBlock> offloadHandling)
{
mcb.ProfilerRequestsInformation.Reset();
Expand All @@ -71,6 +73,10 @@ private static void SendChunkAndWaitForConfirmation(int writeSize, IManagedCommu
mcb.InformationReadByProfiler.Reset();
}

/// <summary>
/// process a results block from the profiler
/// </summary>
/// <param name="mmb"></param>
public byte[] HandleMemoryBlock(IManagedMemoryBlock mmb)
{
mmb.ProfilerHasResults.Reset();
Expand All @@ -88,6 +94,9 @@ public byte[] HandleMemoryBlock(IManagedMemoryBlock mmb)
return newData;
}

/// <summary>
/// Communication is over
/// </summary>
public void Complete()
{
_messageHandler.Complete();
Expand Down
13 changes: 13 additions & 0 deletions main/OpenCover.Framework/Communication/MarshalWapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,24 @@ public interface IMarshalWrapper
/// </summary>
public class MarshalWrapper : IMarshalWrapper
{
/// <summary>
/// Map pinned memory to a structure
/// </summary>
/// <typeparam name="T">The type of the structure</typeparam>
/// <param name="pinnedMemory"></param>
/// <returns></returns>
public T PtrToStructure<T>(IntPtr pinnedMemory)
{
return (T)Marshal.PtrToStructure(pinnedMemory, typeof(T));
}

/// <summary>
/// Map a structure to pinned memory
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="structure"></param>
/// <param name="pinnedMemory"></param>
/// <param name="fDeleteOld"></param>
public void StructureToPtr<T>(T structure, IntPtr pinnedMemory, bool fDeleteOld)
{
Marshal.StructureToPtr(structure, pinnedMemory, fDeleteOld);
Expand Down
14 changes: 14 additions & 0 deletions main/OpenCover.Framework/Communication/MessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ public MessageHandler(IProfilerCommunication profilerCommunication, IMarshalWrap
_memoryManager = memoryManager;
}

/// <summary>
/// Process a Standard Message
/// </summary>
/// <param name="msgType"></param>
/// <param name="mcb"></param>
/// <param name="chunkReady"></param>
/// <param name="offloadHandling"></param>
/// <returns></returns>
public int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Action<int, IManagedCommunicationBlock> chunkReady, Action<ManagedBufferBlock> offloadHandling)
{
IntPtr pinnedMemory = mcb.PinnedDataCommunication.AddrOfPinnedObject();
Expand Down Expand Up @@ -319,6 +327,9 @@ private int HandleTrackProcessMessage(IntPtr pinnedMemory)

private int _readSize;

/// <summary>
/// Maximum size of a base message
/// </summary>
public int ReadSize
{
get
Expand All @@ -344,6 +355,9 @@ public int ReadSize
}
}

/// <summary>
/// Finished
/// </summary>
public void Complete()
{
_profilerCommunication.Stopping();
Expand Down
10 changes: 9 additions & 1 deletion main/OpenCover.Framework/Communication/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace OpenCover.Framework.Communication
/// <summary>
/// The command supportd by the host
/// </summary>
// ReSharper disable InconsistentNaming
// ReSharper disable InconsistentNaming
// ReSharper disable once EnumUnderlyingTypeIsInt
public enum MSG_Type : int
{
/// <summary>
Expand Down Expand Up @@ -338,8 +339,15 @@ public struct MSG_AllocateBuffer_Request
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MSG_AllocateBuffer_Response
{
/// <summary>
/// is the buffer allocated
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool allocated;

/// <summary>
/// The id assigned to the buffer
/// </summary>
public uint bufferId;
}

Expand Down
73 changes: 72 additions & 1 deletion main/OpenCover.Framework/Filter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
Expand All @@ -25,6 +24,10 @@ public class Filter : IFilter
internal IList<RegexFilter> ExcludedAttributes { get; private set; }
internal IList<RegexFilter> ExcludedFiles { get; private set; }
internal IList<RegexFilter> TestFiles { get; private set; }

/// <summary>
/// Are the filters supplied as reguar expressions
/// </summary>
public bool RegExFilters { get; private set; }


Expand All @@ -42,6 +45,13 @@ public Filter(bool useRegexFilters = false)
RegExFilters = useRegexFilters;
}

/// <summary>
/// Decides whether an assembly should be included in the instrumentation
/// </summary>
/// <param name="processName">The name of the process being profiled</param>
/// <param name="assemblyName">the 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 processName, string assemblyName)
{
processName = Path.GetFileNameWithoutExtension(processName);
Expand All @@ -65,6 +75,13 @@ public bool UseAssembly(string processName, string assemblyName)
return false;
}

/// <summary>
/// Determine if an [assemblyname]classname pair matches the current Exclusion or Inclusion filters
/// </summary>
/// <param name="processName">The name of the process</param>
/// <param name="assemblyName">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 processName, string assemblyName, string className)
{
if (string.IsNullOrEmpty(processName) || string.IsNullOrEmpty(assemblyName) || string.IsNullOrEmpty(className))
Expand Down Expand Up @@ -96,11 +113,23 @@ public bool InstrumentClass(string processName, 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>
/// <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)
{
return InstrumentClass(Guid.NewGuid().ToString(), assemblyName, className);
}

/// <summary>
/// Add a filter
/// </summary>
/// <param name="assemblyClassName">A filter is of the format (+ or -)[assemblyName]className, wildcards are allowed. <br/>
/// i.e. -[mscorlib], -[System.*]*, +[App.*]*, +[*]*
/// </param>
public void AddFilter(string assemblyClassName)
{
string assemblyName;
Expand Down Expand Up @@ -154,11 +183,20 @@ private static InvalidOperationException InvalidFilterFormatException(string ass
return new InvalidOperationException(string.Format("The supplied filter '{0}' does not meet the required format for a filter +-[assemblyname]classname", assemblyClassName));
}

/// <summary>
/// Add attribute exclusion filters
/// </summary>
/// <param name="exclusionFilters">An array of filters that are used to wildcard match an attribute</param>
public void AddAttributeExclusionFilters(string[] exclusionFilters)
{
ExcludedAttributes.AddFilters(exclusionFilters, RegExFilters);
}

/// <summary>
/// Is this entity (method/type) excluded due to an attributeFilter
/// </summary>
/// <param name="entity">The entity to test</param>
/// <returns></returns>
public bool ExcludeByAttribute(IMemberDefinition entity)
{
if (ExcludedAttributes.Count == 0)
Expand Down Expand Up @@ -207,6 +245,11 @@ where excludeAttribute.IsMatchingExpression(customAttribute.AttributeType.FullNa
select excludeAttribute).Any();
}

/// <summary>
/// Is this entity excluded due to an attributeFilter
/// </summary>
/// <param name="entity">The entity to test</param>
/// <returns></returns>
public bool ExcludeByAttribute(AssemblyDefinition entity)
{
if (ExcludedAttributes.Count == 0)
Expand All @@ -215,6 +258,11 @@ public bool ExcludeByAttribute(AssemblyDefinition entity)
return ExcludeByAttribute((ICustomAttributeProvider)entity);
}

/// <summary>
/// Is this file excluded
/// </summary>
/// <param name="fileName">The name of the file to test</param>
/// <returns></returns>
public bool ExcludeByFile(string fileName)
{
if (ExcludedFiles.Count == 0 || string.IsNullOrWhiteSpace(fileName))
Expand All @@ -223,11 +271,20 @@ public bool ExcludeByFile(string fileName)
return ExcludedFiles.Any(excludeFile => excludeFile.IsMatchingExpression(fileName));
}

/// <summary>
/// Add file exclusion filters
/// </summary>
/// <param name="exclusionFilters"></param>
public void AddFileExclusionFilters(string[] exclusionFilters)
{
ExcludedFiles.AddFilters(exclusionFilters, RegExFilters);
}

/// <summary>
/// Decides whether an assembly should be analysed for test methods
/// </summary>
/// <param name="assemblyName">the name of the assembly under profile</param>
/// <returns>true - if the assembly matches the test assembly filter</returns>
public bool UseTestAssembly(string assemblyName)
{
if (TestFiles.Count == 0 || string.IsNullOrWhiteSpace(assemblyName))
Expand All @@ -236,11 +293,20 @@ public bool UseTestAssembly(string assemblyName)
return TestFiles.Any(file => file.IsMatchingExpression(assemblyName));
}

/// <summary>
/// Add test file filters
/// </summary>
/// <param name="testFilters"></param>
public void AddTestFileFilters(string[] testFilters)
{
TestFiles.AddFilters(testFilters, RegExFilters);
}

/// <summary>
/// Is the method an auto-implemented property get/set
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
public bool IsAutoImplementedProperty(MethodDefinition method)
{
if ((method.IsSetter || method.IsGetter) && method.HasCustomAttributes)
Expand All @@ -250,6 +316,11 @@ public bool IsAutoImplementedProperty(MethodDefinition method)
return false;
}

/// <summary>
/// Should we instrument this asssembly
/// </summary>
/// <param name="processName"></param>
/// <returns></returns>
public bool InstrumentProcess(string processName)
{
if (string.IsNullOrEmpty(processName))
Expand Down
5 changes: 5 additions & 0 deletions main/OpenCover.Framework/ICommandLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,10 @@ public interface ICommandLine
/// Should auto implemented properties be skipped
/// </summary>
bool SkipAutoImplementedProperties { get; }

/// <summary>
/// Sets the 'short' timeout between profiler and host
/// </summary>
int CommunicationTimeout { get; }
}
}
Loading