diff --git a/ReleaseNotes.tmp b/ReleaseNotes.tmp
index f1750c803..3cc108b09 100644
--- a/ReleaseNotes.tmp
+++ b/ReleaseNotes.tmp
@@ -1,4 +1,11 @@
Version [[version]]
+#329 address ArgumentOutOfRangeException (potentially related to #274) (fix for VS2015)
+#335 error on unrecognized arguments/prefixes (fix)
+#328 exclude types when declaredtype is excluded (fix-feature)
+#302 ignore branches in known autogenerated sequences (feature)
+#310 skip first switch (if applicable) in a generated MoveNext (feature)
+
+Version 4.6.166
#323 push releases and candidates to github via appveyor (prj-mgmt)
#315 update nuget package (fix for VS2015)
#320 update packages (fix for VS2015)
diff --git a/appveyor.yml b/appveyor.yml
index 8b8063600..58d19fbce 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,5 @@
version: 4.6.{build}
+skip_tags: true
os: Unstable
shallow_clone: true
environment:
@@ -60,4 +61,4 @@ notifications:
on_build_failure: true
on_build_status_changed: true
on_success:
-- build dogfood-release
\ No newline at end of file
+- build dogfood-release
diff --git a/build/opencover.build b/build/opencover.build
index f9725f7af..c1c4ccf93 100644
--- a/build/opencover.build
+++ b/build/opencover.build
@@ -1,20 +1,18 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
@@ -26,40 +24,40 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
- Output file doesn't exist in ${expected.output}
-
+
+ Output file doesn't exist in ${expected.output}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
-
-
-
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/default.build b/default.build
index f4b14db91..6ce048f53 100644
--- a/default.build
+++ b/default.build
@@ -50,7 +50,7 @@
tofile="${solution.folder}/bin/zip/opencover.${buildnumber.major}.${buildnumber.minor}.${buildnumber.build}.zip" />
-
+
@@ -61,12 +61,7 @@
-
-
-
-
-
-
+
@@ -95,6 +90,6 @@
-
+
\ No newline at end of file
diff --git a/main/OpenCover.Console/Program.cs b/main/OpenCover.Console/Program.cs
index 38918ff0f..7ec00e6e3 100644
--- a/main/OpenCover.Console/Program.cs
+++ b/main/OpenCover.Console/Program.cs
@@ -541,7 +541,9 @@ private static bool ParseCommandLine(string[] args, out CommandLineParser parser
}
catch (Exception ex)
{
+ System.Console.WriteLine("");
System.Console.WriteLine("Incorrect Arguments: {0}", ex.Message);
+ System.Console.WriteLine("");
System.Console.WriteLine(parser.Usage());
return false;
}
diff --git a/main/OpenCover.Framework/CommandLineParser.cs b/main/OpenCover.Framework/CommandLineParser.cs
index de34a7db1..07220b3d2 100644
--- a/main/OpenCover.Framework/CommandLineParser.cs
+++ b/main/OpenCover.Framework/CommandLineParser.cs
@@ -145,6 +145,8 @@ public string Usage()
///
public void ExtractAndValidateArguments()
{
+ ParseArguments();
+
foreach (var key in ParsedArguments.Keys)
{
var lower = key.ToLowerInvariant();
@@ -247,7 +249,7 @@ public void ExtractAndValidateArguments()
PrintVersion = true;
break;
default:
- throw new InvalidOperationException(string.Format("The argument {0} is not recognised", key));
+ throw new InvalidOperationException(string.Format("The argument '-{0}' is not recognised", key));
}
}
diff --git a/main/OpenCover.Framework/CommandLineParserBase.cs b/main/OpenCover.Framework/CommandLineParserBase.cs
index 853fc924a..57b968efd 100644
--- a/main/OpenCover.Framework/CommandLineParserBase.cs
+++ b/main/OpenCover.Framework/CommandLineParserBase.cs
@@ -21,21 +21,29 @@ protected CommandLineParserBase(string[] arguments)
{
_arguments = arguments;
ParsedArguments = new Dictionary();
- ParseArguments();
}
protected IDictionary ParsedArguments { get; private set; }
-
- private void ParseArguments()
+
+ ///
+ /// Parse the arguments
+ ///
+ protected void ParseArguments()
{
if (_arguments == null) return;
+ if (ParsedArguments.Count > 0) return;
foreach (var argument in _arguments)
{
var trimmed = argument.Trim();
- if (!trimmed.StartsWith("-")) continue;
+ if (string.IsNullOrEmpty(trimmed)) continue;
+
+ if (!trimmed.StartsWith("-"))
+ throw new InvalidOperationException(string.Format("The argument '{0}' is not recognised", argument));
+
trimmed = trimmed.Substring(1);
if (string.IsNullOrEmpty(trimmed)) continue;
+
var colonidx = trimmed.IndexOf(':');
if (colonidx>0)
{
diff --git a/main/OpenCover.Framework/Communication/CommunicationManager.cs b/main/OpenCover.Framework/Communication/CommunicationManager.cs
index 15e3a470d..cc2fd44ec 100644
--- a/main/OpenCover.Framework/Communication/CommunicationManager.cs
+++ b/main/OpenCover.Framework/Communication/CommunicationManager.cs
@@ -16,7 +16,7 @@ public interface ICommunicationManager
///
///
///
- void HandleCommunicationBlock(IManagedCommunicationBlock mcb, Action offloadHandling);
+ void HandleCommunicationBlock(IManagedCommunicationBlock mcb, Action offloadHandling);
///
/// process a results block from the profiler
@@ -46,7 +46,7 @@ public CommunicationManager(IMessageHandler messageHandler)
_messageHandler = messageHandler;
}
- public void HandleCommunicationBlock(IManagedCommunicationBlock mcb, Action offloadHandling)
+ public void HandleCommunicationBlock(IManagedCommunicationBlock mcb, Action offloadHandling)
{
mcb.ProfilerRequestsInformation.Reset();
diff --git a/main/OpenCover.Framework/Communication/MessageHandler.cs b/main/OpenCover.Framework/Communication/MessageHandler.cs
index ba3641d84..d8ee26c8b 100644
--- a/main/OpenCover.Framework/Communication/MessageHandler.cs
+++ b/main/OpenCover.Framework/Communication/MessageHandler.cs
@@ -16,7 +16,7 @@ namespace OpenCover.Framework.Communication
{
public interface IMessageHandler
{
- int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Action chunkReady, Action offloadHandling);
+ int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Action chunkReady, Action offloadHandling);
int ReadSize { get; }
void Complete();
}
@@ -38,7 +38,7 @@ public MessageHandler(IProfilerCommunication profilerCommunication, IMarshalWrap
}
// TODO: change pinnedMemory to an byte[], pass in mcb as well
- public int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Action chunkReady, Action offloadHandling)
+ public int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Action chunkReady, Action offloadHandling)
{
IntPtr pinnedMemory = mcb.PinnedDataCommunication.AddrOfPinnedObject();
var writeSize = 0;
@@ -153,7 +153,20 @@ public int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Act
writeSize = Marshal.SizeOf(typeof(MSG_AllocateBuffer_Response));
_bufferId++;
- offloadHandling(block.Item1, block.Item2);
+ offloadHandling(block);
+ }
+ break;
+
+ case MSG_Type.MSG_CloseChannel:
+ {
+ var msgCC = _marshalWrapper.PtrToStructure(pinnedMemory);
+ var bufferId = msgCC.bufferId;
+
+ var responseCC = new MSG_CloseChannel_Response { done = true };
+ _marshalWrapper.StructureToPtr(responseCC, pinnedMemory, false);
+ writeSize = Marshal.SizeOf(typeof(MSG_CloseChannel_Response));
+
+ _memoryManager.DeactivateMemoryBuffer(bufferId);
}
break;
}
@@ -180,6 +193,8 @@ public int ReadSize
Marshal.SizeOf(typeof(MSG_TrackMethod_Response)),
Marshal.SizeOf(typeof(MSG_AllocateBuffer_Request)),
Marshal.SizeOf(typeof(MSG_AllocateBuffer_Response)),
+ Marshal.SizeOf(typeof(MSG_CloseChannel_Request)),
+ Marshal.SizeOf(typeof(MSG_CloseChannel_Response)),
}).Max();
}
return _readSize;
diff --git a/main/OpenCover.Framework/Communication/Messages.cs b/main/OpenCover.Framework/Communication/Messages.cs
index 23bc0fb63..6bdfccfef 100644
--- a/main/OpenCover.Framework/Communication/Messages.cs
+++ b/main/OpenCover.Framework/Communication/Messages.cs
@@ -14,6 +14,7 @@ public enum MSG_Type : int
MSG_GetBranchPoints = 3,
MSG_TrackMethod = 4,
MSG_AllocateMemoryBuffer = 5,
+ MSG_CloseChannel = 6,
}
public enum MSG_IdType : uint
@@ -132,4 +133,18 @@ public struct MSG_AllocateBuffer_Response
public uint bufferId;
}
+ [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
+ public struct MSG_CloseChannel_Request
+ {
+ public MSG_Type type;
+ public uint bufferId;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct MSG_CloseChannel_Response
+ {
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool done;
+ }
+
}
diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs
index b1ff38a39..e15e47d78 100644
--- a/main/OpenCover.Framework/Filter.cs
+++ b/main/OpenCover.Framework/Filter.cs
@@ -5,6 +5,7 @@
//
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
@@ -152,10 +153,13 @@ public bool ExcludeByAttribute(IMemberDefinition entity)
while (true)
{
- if (entity == null || !entity.HasCustomAttributes)
+ if (entity == null)
return false;
- if (ExcludeByAttribute((ICustomAttributeProvider) entity))
+ if (ExcludeByAttribute((ICustomAttributeProvider)entity))
+ return true;
+
+ if (ExcludeByAttribute(entity.DeclaringType))
return true;
if (entity.DeclaringType == null || !entity.Name.StartsWith("<"))
diff --git a/main/OpenCover.Framework/Manager/IMemoryManager.cs b/main/OpenCover.Framework/Manager/IMemoryManager.cs
index fabe1bc56..a0556f6bd 100644
--- a/main/OpenCover.Framework/Manager/IMemoryManager.cs
+++ b/main/OpenCover.Framework/Manager/IMemoryManager.cs
@@ -4,10 +4,24 @@
namespace OpenCover.Framework.Manager
{
+ public class ManagedBufferBlock
+ {
+ public ManagedBufferBlock()
+ {
+ Active = true;
+ }
+ public IManagedCommunicationBlock CommunicationBlock { get; set; }
+ public IManagedMemoryBlock MemoryBlock { get; set; }
+ public uint BufferId { get; set; }
+ public bool Active { get; set; }
+ }
+
public interface IMemoryManager : IDisposable
{
void Initialise(string nameSpace, string key, IEnumerable servicePrincipal);
- Tuple AllocateMemoryBuffer(int bufferSize, uint bufferId);
- IList> GetBlocks { get; }
+ ManagedBufferBlock AllocateMemoryBuffer(int bufferSize, uint bufferId);
+ IList GetBlocks { get; }
+ void DeactivateMemoryBuffer(uint bufferId);
+ void RemoveDeactivatedBlocks();
}
}
\ No newline at end of file
diff --git a/main/OpenCover.Framework/Manager/MemoryManager.cs b/main/OpenCover.Framework/Manager/MemoryManager.cs
index d9d639dc3..116e77276 100644
--- a/main/OpenCover.Framework/Manager/MemoryManager.cs
+++ b/main/OpenCover.Framework/Manager/MemoryManager.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
@@ -19,7 +20,7 @@ public class MemoryManager : IMemoryManager
private string _key;
private readonly object _lockObject = new object();
- private readonly IList> _blocks = new List>();
+ private readonly IList _blocks = new List();
///
///
@@ -118,6 +119,7 @@ internal ManagedMemoryBlock(string @namespace, string key, int bufferSize, int b
public void Dispose()
{
+ Debug.WriteLine("*** disposing memory block ***");
StreamAccessorResults.Dispose();
_mmfResults.Dispose();
}
@@ -207,6 +209,7 @@ internal ManagedCommunicationBlock(string @namespace, string key, int bufferSize
public void Dispose()
{
+ Debug.WriteLine("*** disposing communication block ***");
StreamAccessorComms.Dispose();
_memoryMappedFile.Dispose();
PinnedDataCommunication.Free();
@@ -238,37 +241,75 @@ public void Initialise(string @namespace, string key, IEnumerable servic
///
///
///
- public Tuple AllocateMemoryBuffer(int bufferSize, uint bufferId)
+ public ManagedBufferBlock AllocateMemoryBuffer(int bufferSize, uint bufferId)
{
if (!_isIntialised) return null;
lock (_lockObject)
{
- var tuple = new Tuple(
- new ManagedCommunicationBlock(_namespace, _key, bufferSize, (int)bufferId, _servicePrincipal),
- new ManagedMemoryBlock(_namespace, _key, bufferSize, (int)bufferId, _servicePrincipal));
+ var tuple = new ManagedBufferBlock
+ {
+ CommunicationBlock =
+ new ManagedCommunicationBlock(_namespace, _key, bufferSize, (int) bufferId, _servicePrincipal),
+ MemoryBlock =
+ new ManagedMemoryBlock(_namespace, _key, bufferSize, (int) bufferId, _servicePrincipal),
+ BufferId = bufferId
+ };
_blocks.Add(tuple);
return tuple;
}
}
+
///
/// get a pair of communication+memory blocks
///
- public IList> GetBlocks
+ public IList GetBlocks
{
get { return _blocks; }
}
+ ///
+ /// deactivate a memory block
+ ///
+ ///
+ public void DeactivateMemoryBuffer(uint bufferId)
+ {
+ lock (_lockObject)
+ {
+ var block = _blocks.FirstOrDefault(b => b.BufferId == bufferId);
+ if (block == null) return;
+ block.Active = false;
+ }
+ }
+
+ ///
+ /// remove deactivated blocks
+ ///
+ public void RemoveDeactivatedBlocks()
+ {
+ lock (_lockObject)
+ {
+ var list = _blocks.Where(b => !b.Active).ToList();
+ foreach (var b in list)
+ {
+ Debug.WriteLine("*** removing deactivated ***");
+ b.CommunicationBlock.Dispose();
+ b.MemoryBlock.Dispose();
+ _blocks.RemoveAt(_blocks.IndexOf(b));
+ }
+ }
+ }
+
public void Dispose()
{
//Console.WriteLine("Disposing...");
lock (_lockObject)
{
- foreach(var block in _blocks)
+ foreach(var block in _blocks.Where(b => b.Active))
{
- block.Item1.Dispose();
- block.Item2.Dispose();
+ block.CommunicationBlock.Dispose();
+ block.MemoryBlock.Dispose();
}
_blocks.Clear();
}
diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs
index 1d700b8c8..eb062f5f9 100644
--- a/main/OpenCover.Framework/Manager/ProfilerManager.cs
+++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs
@@ -173,12 +173,12 @@ private void ProcessMessages(WaitHandle[] handles)
break;
case 1:
- _communicationManager.HandleCommunicationBlock(_mcb, (mcb, mmb) => threadHandles.Add(StartProcessingThread(mcb, mmb)));
+ _communicationManager.HandleCommunicationBlock(_mcb, block => threadHandles.Add(StartProcessingThread(block)));
break;
}
} while (_continueWait);
- foreach (var block in _memoryManager.GetBlocks.Select(b => b.Item2))
+ foreach (var block in _memoryManager.GetBlocks.Where(b => b.Active).Select(b => b.MemoryBlock))
{
var data = new byte[block.BufferSize];
block.StreamAccessorResults.Seek(0, SeekOrigin.Begin);
@@ -210,46 +210,46 @@ private void ProcessMessages(WaitHandle[] handles)
_messageQueue.Enqueue(new byte[0]);
}
- private Tuple StartProcessingThread(IManagedCommunicationBlock communicationBlock, IManagedMemoryBlock memoryBlock)
+ private Tuple StartProcessingThread(ManagedBufferBlock block)
{
var terminateThread = new ManualResetEvent(false);
var threadTerminated = new ManualResetEvent(false);
using (var threadActivated = new AutoResetEvent(false))
{
- ThreadPool.QueueUserWorkItem(ProcessBlock(communicationBlock, memoryBlock, terminateThread,
+ ThreadPool.QueueUserWorkItem(ProcessBlock(block, terminateThread,
threadActivated, threadTerminated));
threadActivated.WaitOne();
}
return new Tuple(terminateThread, threadTerminated);
}
- private WaitCallback ProcessBlock(IManagedCommunicationBlock communicationBlock, IManagedMemoryBlock memoryBlock,
+ private WaitCallback ProcessBlock(ManagedBufferBlock block,
WaitHandle terminateThread, EventWaitHandle threadActivated, EventWaitHandle threadTerminated)
{
return state =>
{
var processEvents = new []
{
- communicationBlock.ProfilerRequestsInformation,
- memoryBlock.ProfilerHasResults,
+ block.CommunicationBlock.ProfilerRequestsInformation,
+ block.MemoryBlock.ProfilerHasResults,
terminateThread
};
threadActivated.Set();
- while(true)
+ while(block.Active)
{
switch (WaitHandle.WaitAny(processEvents))
{
case 0:
- _communicationManager.HandleCommunicationBlock(communicationBlock, (cB, mB) => { });
+ _communicationManager.HandleCommunicationBlock(block.CommunicationBlock, b => { });
break;
case 1:
- var data = _communicationManager.HandleMemoryBlock(memoryBlock);
+ var data = _communicationManager.HandleMemoryBlock(block.MemoryBlock);
// don't let the queue get too big as using too much memory causes
// problems i.e. the target process closes down but the host takes
// ages to shutdown; this is a compromise.
- _messageQueue.Enqueue(data);
+ _messageQueue.Enqueue(data);
if (_messageQueue.Count > 400)
{
do
@@ -263,6 +263,8 @@ private WaitCallback ProcessBlock(IManagedCommunicationBlock communicationBlock,
return;
}
}
+ threadTerminated.Set();
+ _memoryManager.RemoveDeactivatedBlocks();
};
}
}
diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs
index fb284030c..79e57e234 100644
--- a/main/OpenCover.Framework/Persistance/BasePersistance.cs
+++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs
@@ -489,6 +489,12 @@ public string GetClassFullName(string modulePath, int functionToken)
public void SaveVisitData(byte[] data)
{
var nCount = BitConverter.ToUInt32(data, 0);
+ if (nCount > (data.Count()/4) - 1)
+ {
+ _logger.DebugFormat("Failed to process points as count ({0}) exceeded available buffer size ({1})",
+ nCount, (data.Count()/4) - 1);
+ return;
+ }
for (int i = 0, idx = 4; i < nCount; i++, idx += 4)
{
var spid = BitConverter.ToUInt32(data, idx);
diff --git a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs
index cf65e1c75..fab23a7e0 100644
--- a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs
+++ b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs
@@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Mdb;
@@ -386,11 +387,19 @@ private void GetBranchPointsForToken(int token, List list)
try
{
UInt32 ordinal = 0;
+ var instructions = methodDefinition.SafeGetMethodBody().Instructions;
+
+ // if method is generated MoveNext skip switch if it is the first branch
+ var skipFirstSwitch = Regex.IsMatch(methodDefinition.FullName, @"\<.+\>d__\d+::MoveNext\(\)$");
- foreach (var instruction in methodDefinition.SafeGetMethodBody().Instructions)
+ foreach (var instruction in instructions.Where(instruction => instruction.OpCode.FlowControl == FlowControl.Cond_Branch))
{
- if (instruction.OpCode.FlowControl != FlowControl.Cond_Branch)
+ if (instruction.OpCode.Code == Code.Switch && skipFirstSwitch)
+ {
+ skipFirstSwitch = false;
continue;
+ }
+ skipFirstSwitch = false;
if (BranchIsInGeneratedFinallyBlock(instruction, methodDefinition)) continue;
@@ -426,7 +435,6 @@ private void GetBranchPointsForToken(int token, List list)
: new List(),
EndOffset = pathOffsetList.Last()
};
- list.Add(path0);
// Add Conditional Branch (Path=1)
if (instruction.OpCode.Code != Code.Switch)
@@ -452,7 +460,42 @@ private void GetBranchPointsForToken(int token, List list)
: new List(),
EndOffset = pathOffsetList.Last()
};
- list.Add(path1);
+
+ // only add branch if branch does not match a known sequence
+ // e.g. auto generated field assignment
+ // or encapsulates at least one sequence point
+ var offsets = new[]
+ {
+ path0.Offset,
+ path0.EndOffset,
+ path1.Offset,
+ path1.EndOffset
+ };
+
+ var ignoreSequences = new[]
+ {
+ new []{ Code.Brtrue_S, Code.Ldnull, Code.Ldftn, Code.Newobj, Code.Stsfld, Code.Br_S, Code.Ldsfld}, // CachedAnonymousMethodDelegate field allocation - debug
+ new []{ Code.Brtrue_S, Code.Ldnull, Code.Ldftn, Code.Newobj, Code.Stsfld, Code.Ldsfld} // CachedAnonymousMethodDelegate field allocation
+ };
+
+ var bs = offsets.Min();
+ var be = offsets.Max();
+
+ var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList();
+
+ var match = ignoreSequences
+ .Where(ignoreSequence => range.Count() >= ignoreSequence.Count())
+ .Select(x => x.Zip(range, (code, i1) => new {Code1 = code, Code2 = i1.OpCode.Code}).All(y => y.Code1 == y.Code2))
+ .Any();
+
+ var count = range
+ .Count(i => i.SequencePoint != null);
+
+ if (!match || count > 0)
+ {
+ list.Add(path0);
+ list.Add(path1);
+ }
}
else // instruction.OpCode.Code == Code.Switch
{
@@ -460,6 +503,7 @@ private void GetBranchPointsForToken(int token, List list)
if (branchInstructions == null || branchInstructions.Length == 0)
return;
+ list.Add(path0);
// Add Conditional Branches (Path>0)
foreach (var @case in branchInstructions)
{
@@ -548,7 +592,7 @@ private Instruction FindClosestSequencePoints(MethodBody methodBody, Instruction
{
var sequencePointsInMethod = methodBody.Instructions.Where(HasValidSequencePoint).ToList();
if (!sequencePointsInMethod.Any()) return null;
- var idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetCompararer());
+ var idx = sequencePointsInMethod.BinarySearch(instruction, new InstructionByOffsetComparer());
Instruction prev;
if (idx < 0)
{
@@ -570,7 +614,7 @@ private bool HasValidSequencePoint(Instruction instruction)
return instruction.SequencePoint != null && instruction.SequencePoint.StartLine != StepOverLineCode;
}
- private class InstructionByOffsetCompararer : IComparer
+ private class InstructionByOffsetComparer : IComparer
{
public int Compare(Instruction x, Instruction y)
{
diff --git a/main/OpenCover.Profiler/CodeCoverage.cpp b/main/OpenCover.Profiler/CodeCoverage.cpp
index f2225e315..30b4f119b 100644
--- a/main/OpenCover.Profiler/CodeCoverage.cpp
+++ b/main/OpenCover.Profiler/CodeCoverage.cpp
@@ -164,9 +164,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::Shutdown( void)
if (m_chainedProfiler != NULL)
m_chainedProfiler->Shutdown();
- if (!m_tracingEnabled){
- m_host.SendRemainingThreadBuffers();
- }
+ m_host.CloseChannel(m_tracingEnabled);
WCHAR szExeName[MAX_PATH];
GetModuleFileNameW(NULL, szExeName, MAX_PATH);
@@ -239,6 +237,12 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ModuleAttachedToAssembly(
m_allowModules[modulePath] = m_host.TrackAssembly((LPWSTR)modulePath.c_str(), (LPWSTR)assemblyName.c_str());
m_allowModulesAssemblyMap[modulePath] = assemblyName;
+ if (m_allowModules[modulePath]){
+ ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)"),
+ moduleId, W2CT(modulePath.c_str()),
+ assemblyId, W2CT(assemblyName.c_str()));
+ }
+
return S_OK;
}
diff --git a/main/OpenCover.Profiler/Messages.h b/main/OpenCover.Profiler/Messages.h
index 632ac273a..1c99fbd67 100644
--- a/main/OpenCover.Profiler/Messages.h
+++ b/main/OpenCover.Profiler/Messages.h
@@ -41,6 +41,7 @@ enum MSG_Type : int
MSG_GetBranchPoints = 3,
MSG_TrackMethod = 4,
MSG_AllocateMemoryBuffer = 5,
+ MSG_CloseChannel = 6,
};
enum MSG_IdType : ULONG
@@ -128,6 +129,17 @@ typedef struct _MSG_AllocateBuffer_Response
ULONG ulBufferId;
} MSG_AllocateBuffer_Response;
+typedef struct _MSG_CloseChannel_Request
+{
+ MSG_Type type;
+ ULONG ulBufferId;
+} MSG_CloseChannel_Request;
+
+typedef struct _MSG_CloseChannel_Response
+{
+ BOOL bResponse;
+} MSG_CloseChannel_Response;
+
#pragma pack(pop)
typedef union _MSG_Union
@@ -143,5 +155,7 @@ typedef union _MSG_Union
MSG_TrackMethod_Response trackMethodResponse;
MSG_AllocateBuffer_Request allocateBufferRequest;
MSG_AllocateBuffer_Response allocateBufferResponse;
+ MSG_CloseChannel_Request closeChannelBufferRequest;
+ MSG_CloseChannel_Response closeChannelResponse;
} MSG_Union;
diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp
index 9ff3fcce8..4a14231fc 100644
--- a/main/OpenCover.Profiler/ProfilerCommunication.cpp
+++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp
@@ -19,6 +19,7 @@
ProfilerCommunication::ProfilerCommunication()
{
+ m_bufferId = 0;
}
ProfilerCommunication::~ProfilerCommunication()
@@ -65,6 +66,8 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns)
stream << bufferId;
stream >> memoryKey;
+ m_bufferId = bufferId;
+
memoryKey = m_key + memoryKey;
m_eventProfilerRequestsInformation.Initialise((m_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + memoryKey).c_str());
@@ -106,17 +109,25 @@ void ProfilerCommunication::ThreadCreated(ThreadID threadID, DWORD osThreadID){
ATL::CComCritSecLock lock(m_critThreads);
m_threadmap[threadID] = osThreadID;
auto p = new MSG_SendVisitPoints_Request();
- ::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request));
+ p->count = 0;
+ //::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request));
m_visitmap[osThreadID] = p;
}
MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG osThreadID){
try {
- return m_visitmap[osThreadID];
+ auto result = m_visitmap.find(osThreadID);
+ if (result != m_visitmap.end())
+ return (*result).second;
+
+ auto p = new MSG_SendVisitPoints_Request();
+ ::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request));
+ m_visitmap[osThreadID] = p;
}
catch (...){
auto p = new MSG_SendVisitPoints_Request();
- ::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request));
+ p->count = 0;
+ //::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request));
m_visitmap[osThreadID] = p;
}
return m_visitmap[osThreadID];
@@ -125,15 +136,18 @@ MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG
void ProfilerCommunication::ThreadDestroyed(ThreadID threadID){
ATL::CComCritSecLock lock(m_critThreads);
ULONG osThreadId = m_threadmap[threadID];
- SendThreadVisitPoints(m_visitmap[osThreadId]);
+ auto points = m_visitmap[osThreadId];
+ SendThreadVisitPoints(points);
delete m_visitmap[osThreadId];
m_visitmap[osThreadId] = NULL;
}
void ProfilerCommunication::SendRemainingThreadBuffers(){
for (auto it = m_visitmap.begin(); it != m_visitmap.end(); ++it){
- if (it->second != NULL)
+ if (it->second != NULL){
SendThreadVisitPoints(it->second);
+ //::ZeroMemory(pVisitPoints, sizeof(MSG_SendVisitPoints_Request));
+ }
}
}
@@ -145,8 +159,7 @@ void ProfilerCommunication::AddVisitPointToThreadBuffer(ULONG uniqueId, MSG_IdTy
if (++pVisitPoints->count == VP_BUFFER_SIZE)
{
SendThreadVisitPoints(pVisitPoints);
- //::ZeroMemory(pVisitPoints, sizeof(MSG_SendVisitPoints_Request));
- pVisitPoints->count = 0;
+ //::ZeroMemory(pVisitPoints, sizeof(MSG_SendVisitPoints_Request));
}
}
@@ -154,8 +167,9 @@ void ProfilerCommunication::SendThreadVisitPoints(MSG_SendVisitPoints_Request* p
ATL::CComCritSecLock lock(m_critResults);
if (!hostCommunicationActive) return;
memcpy(m_pVisitPoints, pVisitPoints, sizeof(MSG_SendVisitPoints_Request));
+ pVisitPoints->count = 0;
SendVisitPoints();
- ::ZeroMemory(m_pVisitPoints, sizeof(MAX_MSG_SIZE));
+ //::ZeroMemory(m_pVisitPoints, sizeof(MSG_SendVisitPoints_Request));
m_pVisitPoints->count = 0;
}
@@ -167,7 +181,7 @@ void ProfilerCommunication::AddVisitPointToBuffer(ULONG uniqueId, MSG_IdType msg
if (++m_pVisitPoints->count == VP_BUFFER_SIZE)
{
SendVisitPoints();
- ::ZeroMemory(m_pVisitPoints, sizeof(MAX_MSG_SIZE));
+ //::ZeroMemory(m_pVisitPoints, sizeof(MSG_SendVisitPoints_Request));
m_pVisitPoints->count = 0;
}
}
@@ -333,6 +347,36 @@ bool ProfilerCommunication::AllocateBuffer(LONG bufferSize, ULONG &bufferId)
return response;
}
+void ProfilerCommunication::CloseChannel(bool sendSingleBuffer){
+ if (m_bufferId == 0) return;
+
+
+ if (sendSingleBuffer)
+ SendVisitPoints();
+ else
+ SendRemainingThreadBuffers();
+
+ if (!hostCommunicationActive) return;
+
+ bool response = false;
+
+ RequestInformation(
+ [=]()
+ {
+ m_pMSG->closeChannelBufferRequest.type = MSG_CloseChannel;
+ m_pMSG->closeChannelBufferRequest.ulBufferId = m_bufferId;
+ },
+ [=, &response]()->BOOL
+ {
+ response = m_pMSG->allocateBufferResponse.bResponse == TRUE;
+ return FALSE;
+ }
+ , COMM_WAIT_SHORT
+ , _T("CloseChannel"));
+
+ return;
+}
+
template
void ProfilerCommunication::RequestInformation(BR buildRequest, PR processResults, DWORD dwTimeout, tstring message)
{
diff --git a/main/OpenCover.Profiler/ProfilerCommunication.h b/main/OpenCover.Profiler/ProfilerCommunication.h
index d161c6e3b..54e9e5d56 100644
--- a/main/OpenCover.Profiler/ProfilerCommunication.h
+++ b/main/OpenCover.Profiler/ProfilerCommunication.h
@@ -35,11 +35,11 @@ class ProfilerCommunication
inline void AddTestTailcallPoint(ULONG uniqueId) { AddVisitPointToBuffer(uniqueId, IT_MethodTailcall); }
inline void AddVisitPoint(ULONG uniqueId) { AddVisitPointToBuffer(uniqueId, IT_VisitPoint); }
void AddVisitPointToThreadBuffer(ULONG uniqueId, MSG_IdType msgType);
+ void CloseChannel(bool sendSingleBuffer);
public:
void ThreadCreated(ThreadID threadID, DWORD osThreadID);
void ThreadDestroyed(ThreadID threadID);
- void SendRemainingThreadBuffers();
private:
void AddVisitPointToBuffer(ULONG uniqueId, MSG_IdType msgType);
@@ -47,6 +47,7 @@ class ProfilerCommunication
void SendThreadVisitPoints(MSG_SendVisitPoints_Request* pVisitPoints);
bool GetSequencePoints(mdToken functionToken, WCHAR* pModulePath, WCHAR* pAssemblyName, std::vector &points);
bool GetBranchPoints(mdToken functionToken, WCHAR* pModulePath, WCHAR* pAssemblyName, std::vector &points);
+ void SendRemainingThreadBuffers();
private:
tstring m_key;
@@ -55,6 +56,8 @@ class ProfilerCommunication
template
void RequestInformation(BR buildRequest, PR processResults, DWORD dwTimeout, tstring message);
+ ULONG m_bufferId;
+
private:
CMutex m_mutexCommunication;
CSharedMemory m_memoryCommunication;
diff --git a/main/OpenCover.Simple.Target/OpenCover.Simple.Target.csproj b/main/OpenCover.Simple.Target/OpenCover.Simple.Target.csproj
index d2fb41d11..dde3c75c6 100644
--- a/main/OpenCover.Simple.Target/OpenCover.Simple.Target.csproj
+++ b/main/OpenCover.Simple.Target/OpenCover.Simple.Target.csproj
@@ -88,6 +88,10 @@
+
+ mkdir "$(TargetDir)..\..\test"
+copy "$(TargetDir)$(TargetName).*" "$(TargetDir)..\..\test"
+