From 44dd0a88f2bac0a324dea5555820ee665f1d676c Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Sun, 20 Sep 2015 11:20:45 +1000 Subject: [PATCH 01/41] add image [skip ci] --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4d671b5d4..70a0d0961 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,13 @@ No Git? Don't worry you can download the latest code as a [zip file](http://gith I would like to thank * JetBrains for my Open Source [ReSharper licence](http://www.jetbrains.com/resharper/), + + * [AppVeyor](https://ci.appveyor.com/project/sawilde/opencover) for allowing free build CI services for Open Source projects, * [Coveralls](https://coveralls.io/r/OpenCover/opencover) for allowing free services for Open Source projects, * NDepend for my [NDepend licence](http://www.ndepend.com/), * the guys at [CodeBetter](http://codebetter.com/), [Devlicious](http://devlicio.us/) and [Los Techies](http://lostechies.com/) who orignally arranged my MSDN licence all those years ago without which I doubt I'd have been able to start OpenCover (now no longer needed as we can build OpenCover using the VS2013 Community Edition), * the [NextGenUG](http://www.nxtgenug.net/) and their free swag from where I got lots of useful tools, + I'd also like to thank my family, employers, colleagues and friends for all their support. From fa1b7e300ed5cc95cc0b29fc76f3a59039b5160a Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 21 Sep 2015 06:59:18 +1000 Subject: [PATCH 02/41] use Resharper C++ suggestions - thanks again to JetBrains for supporting OpenCover --- main/OpenCover.Profiler/CodeCoverage.cpp | 18 +- main/OpenCover.Profiler/CodeCoverage.h | 86 ++++--- .../CodeCoverage_Thread.cpp | 8 +- .../CoverageInstrumentation.h | 6 +- main/OpenCover.Profiler/ExceptionHandler.cpp | 11 +- main/OpenCover.Profiler/Instruction.cpp | 3 + main/OpenCover.Profiler/Method.cpp | 124 ++++----- main/OpenCover.Profiler/ProfileBase.h | 184 +++++++------- .../ProfilerCommunication.cpp | 7 +- .../ProfilerCommunication.h | 1 - main/OpenCover.Profiler/ProfilerInfo.h | 1 + main/OpenCover.Profiler/ProfilerInfoBase.h | 240 ++++++++++++------ main/OpenCover.Profiler/SharedMemory.cpp | 12 +- main/OpenCover.Profiler/SharedMemory.h | 4 +- main/OpenCover.Profiler/Synchronization.h | 30 +-- 15 files changed, 417 insertions(+), 318 deletions(-) diff --git a/main/OpenCover.Profiler/CodeCoverage.cpp b/main/OpenCover.Profiler/CodeCoverage.cpp index 0e7cd679f..79718f342 100644 --- a/main/OpenCover.Profiler/CodeCoverage.cpp +++ b/main/OpenCover.Profiler/CodeCoverage.cpp @@ -25,7 +25,7 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ ATLTRACE(_T("::OpenCoverInitialise")); OLECHAR szGuid[40]={0}; - int nCount = ::StringFromGUID2(CLSID_CodeCoverage, szGuid, 40); + ::StringFromGUID2(CLSID_CodeCoverage, szGuid, 40); RELTRACE(L" ::Initialize(...) => CLSID == %s", szGuid); //::OutputDebugStringW(szGuid); @@ -351,14 +351,14 @@ void CCodeCoverage::InstrumentMethod(ModuleID moduleId, Method& method, std::ve CoverageInstrumentation::InsertFunctionCall(instructions, pvsig, (FPTR)pt, seqPoints[0].UniqueId); if (method.IsInstrumented(0, instructions)) return; - CoverageInstrumentation::AddBranchCoverage([pvsig, pt](InstructionList& instructions, ULONG uniqueId)->Instruction* + CoverageInstrumentation::AddBranchCoverage([pvsig, pt](InstructionList& brinstructions, ULONG uniqueId)->Instruction* { - return CoverageInstrumentation::InsertFunctionCall(instructions, pvsig, (FPTR)pt, uniqueId); + return CoverageInstrumentation::InsertFunctionCall(brinstructions, pvsig, (FPTR)pt, uniqueId); }, method, brPoints, seqPoints); - CoverageInstrumentation::AddSequenceCoverage([pvsig, pt](InstructionList& instructions, ULONG uniqueId)->Instruction* + CoverageInstrumentation::AddSequenceCoverage([pvsig, pt](InstructionList& seqinstructions, ULONG uniqueId)->Instruction* { - return CoverageInstrumentation::InsertFunctionCall(instructions, pvsig, (FPTR)pt, uniqueId); + return CoverageInstrumentation::InsertFunctionCall(seqinstructions, pvsig, (FPTR)pt, uniqueId); }, method, seqPoints); } else @@ -370,14 +370,14 @@ void CCodeCoverage::InstrumentMethod(ModuleID moduleId, Method& method, std::ve CoverageInstrumentation::InsertInjectedMethod(instructions, injectedVisitedMethod, seqPoints[0].UniqueId); if (method.IsInstrumented(0, instructions)) return; - CoverageInstrumentation::AddBranchCoverage([injectedVisitedMethod](InstructionList& instructions, ULONG uniqueId)->Instruction* + CoverageInstrumentation::AddBranchCoverage([injectedVisitedMethod](InstructionList& brinstructions, ULONG uniqueId)->Instruction* { - return CoverageInstrumentation::InsertInjectedMethod(instructions, injectedVisitedMethod, uniqueId); + return CoverageInstrumentation::InsertInjectedMethod(brinstructions, injectedVisitedMethod, uniqueId); }, method, brPoints, seqPoints); - CoverageInstrumentation::AddSequenceCoverage([injectedVisitedMethod](InstructionList& instructions, ULONG uniqueId)->Instruction* + CoverageInstrumentation::AddSequenceCoverage([injectedVisitedMethod](InstructionList& seqinstructions, ULONG uniqueId)->Instruction* { - return CoverageInstrumentation::InsertInjectedMethod(instructions, injectedVisitedMethod, uniqueId); + return CoverageInstrumentation::InsertInjectedMethod(seqinstructions, injectedVisitedMethod, uniqueId); }, method, seqPoints); } } diff --git a/main/OpenCover.Profiler/CodeCoverage.h b/main/OpenCover.Profiler/CodeCoverage.h index 8504c87cd..a5241f3ab 100644 --- a/main/OpenCover.Profiler/CodeCoverage.h +++ b/main/OpenCover.Profiler/CodeCoverage.h @@ -48,6 +48,10 @@ class ATL_NO_VTABLE CCodeCoverage : m_runtimeType = COR_PRF_DESKTOP_CLR; m_useOldStyle = false; m_threshold = 0U; + m_tracingEnabled = false; + m_cuckooCriticalToken = 0; + m_cuckooSafeToken = 0; + m_infoHook = nullptr; } DECLARE_REGISTRY_RESOURCEID(IDR_CODECOVERAGE) @@ -71,11 +75,11 @@ END_COM_MAP() void FinalRelease() { - if (m_profilerInfo!=NULL) m_profilerInfo.Release(); - if (m_profilerInfo2!=NULL) m_profilerInfo2.Release(); - if (m_profilerInfo3!=NULL) m_profilerInfo3.Release(); + if (m_profilerInfo != nullptr) m_profilerInfo.Release(); + if (m_profilerInfo2 != nullptr) m_profilerInfo2.Release(); + if (m_profilerInfo3 != nullptr) m_profilerInfo3.Release(); #ifndef _TOOLSETV71 - if (m_profilerInfo4!=NULL) m_profilerInfo4.Release(); + if (m_profilerInfo4 != nullptr) m_profilerInfo4.Release(); #endif } @@ -188,98 +192,98 @@ END_COM_MAP() public: virtual HRESULT STDMETHODCALLTYPE Initialize( - /* [in] */ IUnknown *pICorProfilerInfoUnk); + /* [in] */ IUnknown *pICorProfilerInfoUnk) override; - virtual HRESULT STDMETHODCALLTYPE Shutdown( void); + virtual HRESULT STDMETHODCALLTYPE Shutdown( void) override; virtual HRESULT STDMETHODCALLTYPE ModuleAttachedToAssembly( /* [in] */ ModuleID moduleId, - /* [in] */ AssemblyID assemblyId); + /* [in] */ AssemblyID assemblyId) override; virtual HRESULT STDMETHODCALLTYPE ModuleLoadFinished( /* [in] */ ModuleID moduleId, - /* [in] */ HRESULT hrStatus); + /* [in] */ HRESULT hrStatus) override; virtual HRESULT STDMETHODCALLTYPE JITCompilationStarted( /* [in] */ FunctionID functionId, - /* [in] */ BOOL fIsSafeToBlock); + /* [in] */ BOOL fIsSafeToBlock) override; public: // COR_PRF_MONITOR_APPDOMAIN_LOADS virtual HRESULT STDMETHODCALLTYPE AppDomainCreationStarted( - /* [in] */ AppDomainID appDomainId) + /* [in] */ AppDomainID appDomainId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AppDomainCreationStarted(appDomainId); return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainCreationFinished( /* [in] */ AppDomainID appDomainId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AppDomainCreationFinished(appDomainId, hrStatus); return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownStarted( - /* [in] */ AppDomainID appDomainId) + /* [in] */ AppDomainID appDomainId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AppDomainShutdownStarted(appDomainId); return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownFinished( /* [in] */ AppDomainID appDomainId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AppDomainShutdownFinished(appDomainId, hrStatus); return S_OK; } // COR_PRF_MONITOR_ASSEMBLY_LOADS virtual HRESULT STDMETHODCALLTYPE AssemblyLoadStarted( - /* [in] */ AssemblyID assemblyId) + /* [in] */ AssemblyID assemblyId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AssemblyLoadStarted(assemblyId); return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyLoadFinished( /* [in] */ AssemblyID assemblyId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AssemblyLoadFinished(assemblyId, hrStatus); return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadStarted( - /* [in] */ AssemblyID assemblyId) + /* [in] */ AssemblyID assemblyId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AssemblyUnloadStarted(assemblyId); return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadFinished( /* [in] */ AssemblyID assemblyId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->AssemblyUnloadFinished(assemblyId, hrStatus); return S_OK; } // COR_PRF_MONITOR_MODULE_LOADS virtual HRESULT STDMETHODCALLTYPE ModuleLoadStarted( - /* [in] */ ModuleID moduleId) + /* [in] */ ModuleID moduleId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->ModuleLoadStarted(moduleId); return S_OK; } @@ -294,18 +298,18 @@ END_COM_MAP() //} virtual HRESULT STDMETHODCALLTYPE ModuleUnloadStarted( - /* [in] */ ModuleID moduleId) + /* [in] */ ModuleID moduleId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->ModuleUnloadStarted(moduleId); return S_OK; } virtual HRESULT STDMETHODCALLTYPE ModuleUnloadFinished( /* [in] */ ModuleID moduleId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->ModuleUnloadFinished(moduleId, hrStatus); return S_OK; } @@ -328,17 +332,17 @@ END_COM_MAP() virtual HRESULT STDMETHODCALLTYPE JITCompilationFinished( /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, - /* [in] */ BOOL fIsSafeToBlock) + /* [in] */ BOOL fIsSafeToBlock) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->JITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITFunctionPitched( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->JITFunctionPitched(functionId); return S_OK; } @@ -346,29 +350,29 @@ END_COM_MAP() virtual HRESULT STDMETHODCALLTYPE JITInlining( /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, - /* [out] */ BOOL *pfShouldInline) + /* [out] */ BOOL *pfShouldInline) override { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->JITInlining(callerId, calleeId, pfShouldInline); return S_OK; } // COR_PRF_MONITOR_THREADS virtual HRESULT STDMETHODCALLTYPE ThreadCreated( - /* [in] */ ThreadID threadId); + /* [in] */ ThreadID threadId) override; virtual HRESULT STDMETHODCALLTYPE ThreadDestroyed( - /* [in] */ ThreadID threadId); + /* [in] */ ThreadID threadId) override; virtual HRESULT STDMETHODCALLTYPE ThreadAssignedToOSThread( /* [in] */ ThreadID managedThreadId, - /* [in] */ DWORD osThreadId); + /* [in] */ DWORD osThreadId) override; virtual HRESULT STDMETHODCALLTYPE ThreadNameChanged( /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [in] */ - __in_ecount_opt(cchName) WCHAR name[]); + __in_ecount_opt(cchName) WCHAR name[]) override; }; OBJECT_ENTRY_AUTO(__uuidof(CodeCoverage), CCodeCoverage) diff --git a/main/OpenCover.Profiler/CodeCoverage_Thread.cpp b/main/OpenCover.Profiler/CodeCoverage_Thread.cpp index 921af6db6..62b37ec1e 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Thread.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Thread.cpp @@ -8,7 +8,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadCreated( /* [in] */ ThreadID threadId) { ATLTRACE(_T("::ThreadCreated(%d)"), threadId); - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->ThreadCreated(threadId); return S_OK; } @@ -17,7 +17,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadDestroyed( /* [in] */ ThreadID threadId) { ATLTRACE(_T("::ThreadDestroyed(%d)"), threadId); - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->ThreadDestroyed(threadId); if (!m_tracingEnabled){ @@ -32,7 +32,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadAssignedToOSThread( /* [in] */ DWORD osThreadId) { ATLTRACE(_T("::ThreadAssignedToOSThread(%d, %d)"), managedThreadId, osThreadId); - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->ThreadAssignedToOSThread(managedThreadId, osThreadId); if (!m_tracingEnabled){ @@ -49,7 +49,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadNameChanged( __in_ecount_opt(cchName) WCHAR name[]) { ATLTRACE(_T("::ThreadNameChanged(%d, %s)"), threadId, W2T(name)); - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->ThreadNameChanged(threadId, cchName, name); return S_OK; } diff --git a/main/OpenCover.Profiler/CoverageInstrumentation.h b/main/OpenCover.Profiler/CoverageInstrumentation.h index 1ccbcd6ad..fa223af33 100644 --- a/main/OpenCover.Profiler/CoverageInstrumentation.h +++ b/main/OpenCover.Profiler/CoverageInstrumentation.h @@ -16,7 +16,7 @@ namespace CoverageInstrumentation inline void AddSequenceCoverage(IM instrumentMethod, Method& method, std::vector points) { if (points.size() == 0) return; - for (auto it = points.begin(); it != points.end(); it++) + for (auto it = points.begin(); it != points.end(); ++it) { InstructionList instructions; instrumentMethod(instructions, (*it).UniqueId); @@ -59,7 +59,7 @@ namespace CoverageInstrumentation instructions.push_back(pJumpNext); // collect branches instrumentation - for(auto sbit = pCurrent->m_branches.begin(); sbit != pCurrent->m_branches.end(); sbit++) + for(auto sbit = pCurrent->m_branches.begin(); sbit != pCurrent->m_branches.end(); ++sbit) { idx++; uniqueId = (*std::find_if(points.begin(), points.end(), [pCurrent, idx](BranchPoint &bp){return bp.Offset == pCurrent->m_origOffset && bp.Path == idx;})).UniqueId; @@ -89,7 +89,9 @@ namespace CoverageInstrumentation Instruction* pElse = instrumentMethod(instructions, storedId); pJumpNext->m_branches[0] = pElse; // rewire pJumpNext + // ReSharper disable once CppPossiblyErroneousEmptyStatements for (it = method.m_instructions.begin(); *it != pNext; ++it); + method.m_instructions.insert(it, instructions.begin(), instructions.end()); // restore 'it' position diff --git a/main/OpenCover.Profiler/ExceptionHandler.cpp b/main/OpenCover.Profiler/ExceptionHandler.cpp index 08cac017e..bf68419da 100644 --- a/main/OpenCover.Profiler/ExceptionHandler.cpp +++ b/main/OpenCover.Profiler/ExceptionHandler.cpp @@ -9,12 +9,13 @@ ExceptionHandler::ExceptionHandler(void) { - m_tryStart = NULL; - m_tryEnd = NULL; - m_handlerStart = NULL; - m_handlerEnd = NULL; - m_filterStart = NULL; + m_tryStart = nullptr; + m_tryEnd = nullptr; + m_handlerStart = nullptr; + m_handlerEnd = nullptr; + m_filterStart = nullptr; m_token = 0; + m_handlerType = COR_ILEXCEPTION_CLAUSE_NONE; } diff --git a/main/OpenCover.Profiler/Instruction.cpp b/main/OpenCover.Profiler/Instruction.cpp index 72650958b..c0e3fb6c9 100644 --- a/main/OpenCover.Profiler/Instruction.cpp +++ b/main/OpenCover.Profiler/Instruction.cpp @@ -13,6 +13,7 @@ Instruction::Instruction(void) m_offset = -1; m_isBranch = false; m_origOffset = -1; + m_jump = nullptr; } Instruction::Instruction(CanonicalName operation, ULONGLONG operand) @@ -22,6 +23,7 @@ Instruction::Instruction(CanonicalName operation, ULONGLONG operand) m_offset = -1; m_isBranch = false; m_origOffset = -1; + m_jump = nullptr; } Instruction::Instruction(CanonicalName operation) @@ -31,6 +33,7 @@ Instruction::Instruction(CanonicalName operation) m_offset = -1; m_isBranch = false; m_origOffset = -1; + m_jump = nullptr; } Instruction::~Instruction(void) diff --git a/main/OpenCover.Profiler/Method.cpp b/main/OpenCover.Profiler/Method.cpp index da2c6a48c..8ca129e4a 100644 --- a/main/OpenCover.Profiler/Method.cpp +++ b/main/OpenCover.Profiler/Method.cpp @@ -38,11 +38,11 @@ Method::~Method() void Method::ReadMethod(IMAGE_COR_ILMETHOD* pMethod) { BYTE* pCode; - COR_ILMETHOD_FAT* fatImage = (COR_ILMETHOD_FAT*)&pMethod->Fat; + auto fatImage = static_cast(&pMethod->Fat); if(!fatImage->IsFat()) { ATLTRACE(_T("TINY")); - COR_ILMETHOD_TINY* tinyImage = (COR_ILMETHOD_TINY*)&pMethod->Tiny; + auto tinyImage = static_cast(&pMethod->Tiny); m_header.CodeSize = tinyImage->GetCodeSize(); pCode = tinyImage->GetCode(); ATLTRACE(_T("TINY(%X) => (%d + 1) : %d"), m_header.CodeSize, m_header.CodeSize, m_header.MaxStack); @@ -64,7 +64,7 @@ void Method::ReadMethod(IMAGE_COR_ILMETHOD* pMethod) void Method::WriteMethod(IMAGE_COR_ILMETHOD* pMethod) { BYTE* pCode; - COR_ILMETHOD_FAT* fatImage = (COR_ILMETHOD_FAT*)&pMethod->Fat; + auto fatImage = static_cast(&pMethod->Fat); m_header.Flags &= ~CorILMethod_MoreSects; if (m_exceptions.size() > 0) @@ -80,7 +80,7 @@ void Method::WriteMethod(IMAGE_COR_ILMETHOD* pMethod) for (auto it = m_instructions.begin(); it != m_instructions.end(); ++it) { - OperationDetails &details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; + auto& details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; if (details.op1 == REFPRE) { Write(details.op2); @@ -100,13 +100,13 @@ void Method::WriteMethod(IMAGE_COR_ILMETHOD* pMethod) case Null: break; case Byte: - Write((BYTE)(*it)->m_operand); + Write(static_cast((*it)->m_operand)); break; case Word: - Write((USHORT)(*it)->m_operand); + Write(static_cast((*it)->m_operand)); break; case Dword: - Write((ULONG)(*it)->m_operand); + Write(static_cast((*it)->m_operand)); break; case Qword: Write((*it)->m_operand); @@ -117,7 +117,7 @@ void Method::WriteMethod(IMAGE_COR_ILMETHOD* pMethod) if ((*it)->m_operation == CEE_SWITCH) { - for (std::vector::iterator offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end() ; offsetIter++) + for (auto offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end(); ++offsetIter) { Write(*offsetIter); } @@ -210,17 +210,17 @@ void Method::ReadBody() { if (details.operandSize==1) { - pInstruction->m_branchOffsets.push_back((char)(BYTE)pInstruction->m_operand); + pInstruction->m_branchOffsets.push_back(static_cast(static_cast(pInstruction->m_operand))); } else { - pInstruction->m_branchOffsets.push_back((ULONG)pInstruction->m_operand); + pInstruction->m_branchOffsets.push_back(static_cast(pInstruction->m_operand)); } } if (pInstruction->m_operation == CEE_SWITCH) { - DWORD numbranches = (DWORD)pInstruction->m_operand; + auto numbranches = static_cast(pInstruction->m_operand); while(numbranches-- != 0) pInstruction->m_branchOffsets.push_back(Read()); } @@ -229,7 +229,7 @@ void Method::ReadBody() ReadSections(); - SetBuffer(NULL); + SetBuffer(nullptr); //DumpIL(); @@ -248,7 +248,7 @@ void Method::ReadSections() { if ((m_header.Flags & CorILMethod_MoreSects) == CorILMethod_MoreSects) { - BYTE flags = 0; + BYTE flags; do { Align(); // must be DWORD aligned @@ -258,13 +258,13 @@ void Method::ReadSections() { Advance(-1); int count = ((Read() >> 8) / 24); - for (int i = 0; i < count; i++) + for (auto i = 0; i < count; i++) { - CorExceptionFlag type = (CorExceptionFlag)Read(); - long tryStart = Read(); - long tryEnd = Read(); - long handlerStart = Read(); - long handlerEnd = Read(); + auto type = static_cast(Read()); + auto tryStart = Read(); + auto tryEnd = Read(); + auto handlerStart = Read(); + auto handlerEnd = Read(); long filterStart = 0; ULONG token = 0; switch (type) @@ -276,7 +276,7 @@ void Method::ReadSections() token = Read(); break; } - ExceptionHandler * pSection = new ExceptionHandler(); + auto pSection = new ExceptionHandler(); pSection->m_handlerType = type; pSection->m_tryStart = GetInstructionAtOffset(tryStart); pSection->m_tryEnd = GetInstructionAtOffset(tryStart + tryEnd); @@ -296,11 +296,11 @@ void Method::ReadSections() } else { - int count = (int)(Read() / 12); + auto count = static_cast(Read() / 12); Advance(2); - for (int i = 0; i < count; i++) + for (auto i = 0; i < count; i++) { - CorExceptionFlag type = (CorExceptionFlag)Read(); + auto type = static_cast(Read()); long tryStart = Read(); long tryEnd = Read(); long handlerStart = Read(); @@ -353,7 +353,7 @@ Instruction * Method::GetInstructionAtOffset(long offset) } } _ASSERTE(FALSE); - return NULL; + return nullptr; } /// Gets the Instruction that has (is at) the specified offset. @@ -387,19 +387,19 @@ Instruction * Method::GetInstructionAtOffset(long offset, bool isFinally, bool i if (isFinally || isFault || isFilter || isTyped) { - Instruction *pLast = m_instructions.back(); - OperationDetails &details = Operations::m_mapNameOperationDetails[pLast->m_operation]; + auto pLast = m_instructions.back(); + auto& details = Operations::m_mapNameOperationDetails[pLast->m_operation]; if (offset == pLast->m_offset + details.length + details.operandSize) { // add a code label to hang the clause handler end off - Instruction *pInstruction = new Instruction(CEE_CODE_LABEL); + auto pInstruction = new Instruction(CEE_CODE_LABEL); pInstruction->m_offset = offset; m_instructions.push_back(pInstruction); return pInstruction; } } _ASSERTE(FALSE); - return NULL; + return nullptr; } /// Uses the current offsets and locates the instructions that reside that offset to @@ -412,18 +412,18 @@ void Method::ResolveBranches() for (auto it = m_instructions.begin(); it != m_instructions.end() ; ++it) { (*it)->m_branches.clear(); - OperationDetails &details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; - long baseOffset = (*it)->m_offset + details.length + details.operandSize; + auto& details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; + auto baseOffset = (*it)->m_offset + details.length + details.operandSize; if ((*it)->m_operation == CEE_SWITCH) { - baseOffset += (4*(long)(*it)->m_operand); + baseOffset += (4*static_cast((*it)->m_operand)); } - for (std::vector::iterator offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end() ; offsetIter++) + for (auto offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end() ; ++offsetIter) { - long offset = baseOffset + (*offsetIter); - Instruction * instruction = GetInstructionAtOffset(offset); - if (instruction != NULL) + auto offset = baseOffset + (*offsetIter); + auto instruction = GetInstructionAtOffset(offset); + if (instruction != nullptr) { (*it)->m_branches.push_back(instruction); } @@ -440,7 +440,7 @@ void Method::DumpIL() ATLTRACE(_T("-+-+-+-+-+-+-+-+-+-+-+-+- START -+-+-+-+-+-+-+-+-+-+-+-+")); for (auto it = m_instructions.begin(); it != m_instructions.end() ; ++it) { - OperationDetails &details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; + auto& details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; if (details.operandSize == Null) { ATLTRACE(_T("IL_%04X %s"), (*it)->m_offset, details.stringName); @@ -449,7 +449,7 @@ void Method::DumpIL() { if (details.operandParam == ShortInlineBrTarget || details.operandParam == InlineBrTarget) { - long offset = (*it)->m_offset + (*it)->m_branchOffsets[0] + details.length + details.operandSize; + auto offset = (*it)->m_offset + (*it)->m_branchOffsets[0] + details.length + details.operandSize; ATLTRACE(_T("IL_%04X %s IL_%04X"), (*it)->m_offset, details.stringName, offset); } @@ -482,11 +482,11 @@ void Method::DumpIL() ATLTRACE(_T("IL_%04X %s %X"), (*it)->m_offset, details.stringName, (*it)->m_operand); } } - for (std::vector::iterator offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end() ; offsetIter++) + for (auto offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end() ; ++offsetIter) { if ((*it)->m_operation == CEE_SWITCH) { - long offset = (*it)->m_offset + (4*(long)(*it)->m_operand) + (*offsetIter) + details.length + details.operandSize; + auto offset = (*it)->m_offset + (4*static_cast((*it)->m_operand)) + (*offsetIter) + details.length + details.operandSize; ATLTRACE(_T(" IL_%04X"), offset); } } @@ -497,11 +497,11 @@ void Method::DumpIL() { ATLTRACE(_T("Section %d: %d %04X %04X %04X %04X %04X %08X"), i++, (*it)->m_handlerType, - (*it)->m_tryStart != NULL ? (*it)->m_tryStart->m_offset : 0, - (*it)->m_tryEnd != NULL ? (*it)->m_tryEnd->m_offset : 0, - (*it)->m_handlerStart != NULL ? (*it)->m_handlerStart->m_offset : 0, - (*it)->m_handlerEnd != NULL ? (*it)->m_handlerEnd->m_offset : 0, - (*it)->m_filterStart != NULL ? (*it)->m_filterStart->m_offset : 0, + (*it)->m_tryStart != nullptr ? (*it)->m_tryStart->m_offset : 0, + (*it)->m_tryEnd != nullptr ? (*it)->m_tryEnd->m_offset : 0, + (*it)->m_handlerStart != nullptr ? (*it)->m_handlerStart->m_offset : 0, + (*it)->m_handlerEnd != nullptr ? (*it)->m_handlerEnd->m_offset : 0, + (*it)->m_filterStart != nullptr ? (*it)->m_filterStart->m_offset : 0, (*it)->m_token); } ATLTRACE(_T("-+-+-+-+-+-+-+-+-+-+-+-+- END -+-+-+-+-+-+-+-+-+-+-+-+")); @@ -583,25 +583,25 @@ void Method::RecalculateOffsets() int position = 0; for (auto it = m_instructions.begin(); it != m_instructions.end(); ++it) { - OperationDetails &details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; + auto& details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; (*it)->m_offset = position; position += details.length; position += details.operandSize; if((*it)->m_operation == CEE_SWITCH) { - position += 4*(long)(*it)->m_operand; + position += 4*static_cast((*it)->m_operand); } } for (auto it = m_instructions.begin(); it != m_instructions.end(); ++it) { - OperationDetails &details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; + auto& details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; if ((*it)->m_isBranch) { (*it)->m_branchOffsets.clear(); if((*it)->m_operation == CEE_SWITCH) { - long offset = ((*it)->m_offset + details.length + details.operandSize + (4*(long)(*it)->m_operand)); + auto offset = ((*it)->m_offset + details.length + details.operandSize + (4*static_cast((*it)->m_operand))); for (auto bit = (*it)->m_branches.begin(); bit != (*it)->m_branches.end(); ++bit) { (*it)->m_branchOffsets.push_back((*bit)->m_offset - offset); @@ -610,7 +610,7 @@ void Method::RecalculateOffsets() else { (*it)->m_operand = (*it)->m_branches[0]->m_offset - ((*it)->m_offset + details.length + details.operandSize); - (*it)->m_branchOffsets.push_back((long)(*it)->m_operand); + (*it)->m_branchOffsets.push_back(static_cast((*it)->m_operand)); } } } @@ -624,8 +624,8 @@ void Method::RecalculateOffsets() /// beforehand if any instrumentation has been done long Method::GetMethodSize() { - Instruction * lastInstruction = m_instructions.back(); - OperationDetails &details = Operations::m_mapNameOperationDetails[lastInstruction->m_operation]; + auto lastInstruction = m_instructions.back(); + auto& details = Operations::m_mapNameOperationDetails[lastInstruction->m_operation]; m_header.CodeSize = lastInstruction->m_offset + details.length + details.operandSize; long size = sizeof(IMAGE_COR_ILMETHOD_FAT) + m_header.CodeSize; @@ -636,7 +636,7 @@ long Method::GetMethodSize() m_header.Flags |= CorILMethod_MoreSects; long align = sizeof(DWORD) - 1; size = ((size + align) & ~align); - size += (((long)m_exceptions.size() * 6) + 1) * sizeof(long); + size += ((static_cast(m_exceptions.size()) * 6) + 1) * sizeof(long); } return size; @@ -679,12 +679,12 @@ void Method::InsertInstructionsAtOffset(long offset, const InstructionList &inst clone.push_back(new Instruction(*(*it))); } - long actualOffset = 0; + //long actualOffset; for (auto it = m_instructions.begin(); it != m_instructions.end(); ++it) { if ((*it)->m_offset == offset) { - actualOffset = (*it)->m_offset; + //actualOffset = (*it)->m_offset; m_instructions.insert(++it, clone.begin(), clone.end()); break; } @@ -693,8 +693,8 @@ void Method::InsertInstructionsAtOffset(long offset, const InstructionList &inst for (auto it = m_instructions.begin(); it != m_instructions.end(); ++it) { if ((*it)->m_origOffset == offset) - { - Instruction orig = *(*it); + { + auto orig = *(*it); for (unsigned int i=0;im_jump = NULL; - Instruction* jump = NULL; - Instruction* jumpTo = NULL; - if (next != NULL) + next->m_jump = nullptr; + Instruction* jump; + Instruction* jumpTo; + if (next != nullptr) { while ( next->m_operation == CEE_BR || next->m_operation == CEE_BR_S ) { _ASSERTE(next->m_isBranch); @@ -828,12 +828,12 @@ Instruction* Method::EndOfBranch(Instruction* toFollow) _ASSERTE(next->m_branches[0] != NULL); jumpTo = next->m_branches[0]; _ASSERTE(jumpTo != NULL); - if ( jumpTo == NULL ) break; + if ( jumpTo == nullptr ) break; jump = next; // store last BR instruction next = jumpTo; // store last BR jump-target instruction found (so far) next->m_jump = jump; // set m_jump to last BR instruction } } - return next == NULL? toFollow : next; + return next == nullptr ? toFollow : next; } diff --git a/main/OpenCover.Profiler/ProfileBase.h b/main/OpenCover.Profiler/ProfileBase.h index d5a7c1472..502515e70 100644 --- a/main/OpenCover.Profiler/ProfileBase.h +++ b/main/OpenCover.Profiler/ProfileBase.h @@ -14,303 +14,307 @@ class CProfilerBase : public ICorProfilerCallback3 #endif // ICorProfilerCallback public: + virtual ~CProfilerBase() + { + } + virtual HRESULT STDMETHODCALLTYPE Initialize( - /* [in] */ IUnknown *pICorProfilerInfoUnk) + /* [in] */ IUnknown *pICorProfilerInfoUnk) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE Shutdown( void) + virtual HRESULT STDMETHODCALLTYPE Shutdown( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainCreationStarted( - /* [in] */ AppDomainID appDomainId) + /* [in] */ AppDomainID appDomainId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainCreationFinished( /* [in] */ AppDomainID appDomainId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownStarted( - /* [in] */ AppDomainID appDomainId) + /* [in] */ AppDomainID appDomainId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownFinished( /* [in] */ AppDomainID appDomainId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyLoadStarted( - /* [in] */ AssemblyID assemblyId) + /* [in] */ AssemblyID assemblyId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyLoadFinished( /* [in] */ AssemblyID assemblyId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadStarted( - /* [in] */ AssemblyID assemblyId) + /* [in] */ AssemblyID assemblyId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadFinished( /* [in] */ AssemblyID assemblyId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ModuleLoadStarted( - /* [in] */ ModuleID moduleId) + /* [in] */ ModuleID moduleId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ModuleLoadFinished( /* [in] */ ModuleID moduleId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ModuleUnloadStarted( - /* [in] */ ModuleID moduleId) + /* [in] */ ModuleID moduleId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ModuleUnloadFinished( /* [in] */ ModuleID moduleId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ModuleAttachedToAssembly( /* [in] */ ModuleID moduleId, - /* [in] */ AssemblyID assemblyId) + /* [in] */ AssemblyID assemblyId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ClassLoadStarted( - /* [in] */ ClassID classId) + /* [in] */ ClassID classId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ClassLoadFinished( /* [in] */ ClassID classId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ClassUnloadStarted( - /* [in] */ ClassID classId) + /* [in] */ ClassID classId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ClassUnloadFinished( /* [in] */ ClassID classId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE FunctionUnloadStarted( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITCompilationStarted( /* [in] */ FunctionID functionId, - /* [in] */ BOOL fIsSafeToBlock) + /* [in] */ BOOL fIsSafeToBlock) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITCompilationFinished( /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, - /* [in] */ BOOL fIsSafeToBlock) + /* [in] */ BOOL fIsSafeToBlock) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchStarted( /* [in] */ FunctionID functionId, - /* [out] */ BOOL *pbUseCachedFunction) + /* [out] */ BOOL *pbUseCachedFunction) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchFinished( /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_JIT_CACHE result) + /* [in] */ COR_PRF_JIT_CACHE result) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITFunctionPitched( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE JITInlining( /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, - /* [out] */ BOOL *pfShouldInline) + /* [out] */ BOOL *pfShouldInline) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ThreadCreated( - /* [in] */ ThreadID threadId) + /* [in] */ ThreadID threadId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ThreadDestroyed( - /* [in] */ ThreadID threadId) + /* [in] */ ThreadID threadId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ThreadAssignedToOSThread( /* [in] */ ThreadID managedThreadId, - /* [in] */ DWORD osThreadId) + /* [in] */ DWORD osThreadId) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationStarted( void) + virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationStarted( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RemotingClientSendingMessage( /* [in] */ GUID *pCookie, - /* [in] */ BOOL fIsAsync) + /* [in] */ BOOL fIsAsync) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RemotingClientReceivingReply( /* [in] */ GUID *pCookie, - /* [in] */ BOOL fIsAsync) + /* [in] */ BOOL fIsAsync) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationFinished( void) + virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationFinished( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RemotingServerReceivingMessage( /* [in] */ GUID *pCookie, - /* [in] */ BOOL fIsAsync) + /* [in] */ BOOL fIsAsync) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationStarted( void) + virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationStarted( void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationReturned( void) + virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationReturned( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RemotingServerSendingReply( /* [in] */ GUID *pCookie, - /* [in] */ BOOL fIsAsync) + /* [in] */ BOOL fIsAsync) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE UnmanagedToManagedTransition( /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_TRANSITION_REASON reason ) + /* [in] */ COR_PRF_TRANSITION_REASON reason ) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ManagedToUnmanagedTransition( /* [in] */ FunctionID functionId, - /* [in] */ COR_PRF_TRANSITION_REASON reason) + /* [in] */ COR_PRF_TRANSITION_REASON reason) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendStarted( - /* [in] */ COR_PRF_SUSPEND_REASON suspendReason) + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendFinished( void) + virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendFinished( void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendAborted( void) + virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendAborted( void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RuntimeResumeStarted( void) + virtual HRESULT STDMETHODCALLTYPE RuntimeResumeStarted( void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE RuntimeResumeFinished( void) + virtual HRESULT STDMETHODCALLTYPE RuntimeResumeFinished( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RuntimeThreadSuspended( - /* [in] */ ThreadID threadId) + /* [in] */ ThreadID threadId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RuntimeThreadResumed( - /* [in] */ ThreadID threadId) + /* [in] */ ThreadID threadId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE MovedReferences( /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], - /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ObjectAllocated( /* [in] */ ObjectID objectId, - /* [in] */ ClassID classId) + /* [in] */ ClassID classId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass( /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], - /* [size_is][in] */ ULONG cObjects[ ]) + /* [size_is][in] */ ULONG cObjects[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ObjectReferences( /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, - /* [size_is][in] */ ObjectID objectRefIds[ ]) + /* [size_is][in] */ ObjectID objectRefIds[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RootReferences( /* [in] */ ULONG cRootRefs, - /* [size_is][in] */ ObjectID rootRefIds[ ]) + /* [size_is][in] */ ObjectID rootRefIds[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionThrown( - /* [in] */ ObjectID thrownObjectId) + /* [in] */ ObjectID thrownObjectId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionEnter( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionLeave( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionLeave( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterEnter( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterLeave( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterLeave( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionSearchCatcherFound( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionOSHandlerEnter( - /* [in] */ UINT_PTR __unused) + /* [in] */ UINT_PTR __unused) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionOSHandlerLeave( - /* [in] */ UINT_PTR __unused) + /* [in] */ UINT_PTR __unused) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionEnter( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionLeave( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionLeave( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyEnter( - /* [in] */ FunctionID functionId) + /* [in] */ FunctionID functionId) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyLeave( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyLeave( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter( /* [in] */ FunctionID functionId, - /* [in] */ ObjectID objectId) + /* [in] */ ObjectID objectId) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherLeave( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherLeave( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE COMClassicVTableCreated( /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, - /* [in] */ ULONG cSlots) + /* [in] */ ULONG cSlots) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE COMClassicVTableDestroyed( /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, - /* [in] */ void *pVTable) + /* [in] */ void *pVTable) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherFound( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherFound( void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherExecute( void) + virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherExecute( void) override { return S_OK; } // ICorProfilerCallback2 @@ -319,27 +323,27 @@ class CProfilerBase : public ICorProfilerCallback3 /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [in] */ - __in_ecount_opt(cchName) WCHAR name[ ]) + __in_ecount_opt(cchName) WCHAR name[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted( /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], - /* [in] */ COR_PRF_GC_REASON reason) + /* [in] */ COR_PRF_GC_REASON reason) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE SurvivingReferences( /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], - /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE GarbageCollectionFinished( void) + virtual HRESULT STDMETHODCALLTYPE GarbageCollectionFinished( void) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE FinalizeableObjectQueued( /* [in] */ DWORD finalizerFlags, - /* [in] */ ObjectID objectID) + /* [in] */ ObjectID objectID) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE RootReferences2( @@ -347,16 +351,16 @@ class CProfilerBase : public ICorProfilerCallback3 /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], - /* [size_is][in] */ UINT_PTR rootIds[ ]) + /* [size_is][in] */ UINT_PTR rootIds[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE HandleCreated( /* [in] */ GCHandleID handleId, - /* [in] */ ObjectID initialObjectId) + /* [in] */ ObjectID initialObjectId) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE HandleDestroyed( - /* [in] */ GCHandleID handleId) + /* [in] */ GCHandleID handleId) override { return S_OK; } // ICorProfilerCallback3 @@ -364,13 +368,13 @@ class CProfilerBase : public ICorProfilerCallback3 virtual HRESULT STDMETHODCALLTYPE InitializeForAttach( /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, - /* [in] */ UINT cbClientData) + /* [in] */ UINT cbClientData) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ProfilerAttachComplete( void) + virtual HRESULT STDMETHODCALLTYPE ProfilerAttachComplete( void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded( void) + virtual HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded( void) override { return S_OK; } #ifndef _TOOLSETV71 @@ -379,41 +383,41 @@ class CProfilerBase : public ICorProfilerCallback3 virtual HRESULT STDMETHODCALLTYPE ReJITCompilationStarted( /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, - /* [in] */ BOOL fIsSafeToBlock) - { return S_OK; } + /* [in] */ BOOL fIsSafeToBlock) override + { return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetReJITParameters( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, - /* [in] */ ICorProfilerFunctionControl *pFunctionControl) - { return S_OK; } + /* [in] */ ICorProfilerFunctionControl *pFunctionControl) override + { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ReJITCompilationFinished( /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, - /* [in] */ BOOL fIsSafeToBlock) + /* [in] */ BOOL fIsSafeToBlock) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ReJITError( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, - /* [in] */ HRESULT hrStatus) + /* [in] */ HRESULT hrStatus) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE MovedReferences2( /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], - /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) override { return S_OK; } virtual HRESULT STDMETHODCALLTYPE SurvivingReferences2( /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], - /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) - { return S_OK; } + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) override + { return S_OK; } // ICorProfilerCallback5 public: @@ -421,7 +425,7 @@ class CProfilerBase : public ICorProfilerCallback3 /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], - /* [size_is][in] */ GCHandleID rootIds[ ]) + /* [size_is][in] */ GCHandleID rootIds[ ]) override { return S_OK; } #endif diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp index 0e7501ce7..620ba9583 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.cpp +++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp @@ -20,6 +20,9 @@ ProfilerCommunication::ProfilerCommunication() { m_bufferId = 0; + m_pMSG = nullptr; + m_pVisitPoints = nullptr; + hostCommunicationActive = false; } ProfilerCommunication::~ProfilerCommunication() @@ -205,10 +208,10 @@ MSG_SendVisitPoints_Request* ProfilerCommunication::AllocateVisitMap(DWORD osThr } MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG osThreadID){ - MSG_SendVisitPoints_Request * p = NULL; + MSG_SendVisitPoints_Request * p; try { p = m_visitmap[osThreadID]; - if (p == NULL) + if (p == nullptr) p = AllocateVisitMap(osThreadID); } catch (...){ diff --git a/main/OpenCover.Profiler/ProfilerCommunication.h b/main/OpenCover.Profiler/ProfilerCommunication.h index 703946720..0d5e0518f 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.h +++ b/main/OpenCover.Profiler/ProfilerCommunication.h @@ -10,7 +10,6 @@ #include "Messages.h" #include -#include #include diff --git a/main/OpenCover.Profiler/ProfilerInfo.h b/main/OpenCover.Profiler/ProfilerInfo.h index 17f985e6f..f61c19d46 100644 --- a/main/OpenCover.Profiler/ProfilerInfo.h +++ b/main/OpenCover.Profiler/ProfilerInfo.h @@ -22,6 +22,7 @@ class ATL_NO_VTABLE CProfilerInfo : public: CProfilerInfo() { + m_pProfilerHook = nullptr; } BEGIN_COM_MAP(CProfilerInfo) diff --git a/main/OpenCover.Profiler/ProfilerInfoBase.h b/main/OpenCover.Profiler/ProfilerInfoBase.h index 59465c7ee..446b6d6ce 100644 --- a/main/OpenCover.Profiler/ProfilerInfoBase.h +++ b/main/OpenCover.Profiler/ProfilerInfoBase.h @@ -8,7 +8,11 @@ using namespace ATL; class CProfilerInfoBase : public ICorProfilerInfo4 { public: - void SetProfilerInfo(IUnknown *pICorProfilerInfoUnk){ + virtual ~CProfilerInfoBase() + { + } + + void SetProfilerInfo(IUnknown *pICorProfilerInfoUnk){ m_pProfilerInfo = pICorProfilerInfoUnk; m_pProfilerInfo2 = pICorProfilerInfoUnk; m_pProfilerInfo3 = pICorProfilerInfoUnk; @@ -24,7 +28,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 public: // ICorProfilerInfo virtual HRESULT STDMETHODCALLTYPE GetClassFromObject( /* [in] */ ObjectID objectId, - /* [out] */ ClassID *pClassId){ + /* [out] */ ClassID *pClassId) override + { //ATLTRACE(_T("GetClassFromObject")); return m_pProfilerInfo->GetClassFromObject(objectId, pClassId); } @@ -32,7 +37,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, - /* [out] */ ClassID *pClassId){ + /* [out] */ ClassID *pClassId) override + { //ATLTRACE(_T("GetClassFromToken")); return m_pProfilerInfo->GetClassFromToken(moduleId, typeDef, pClassId); } @@ -40,20 +46,23 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetCodeInfo( /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, - /* [out] */ ULONG *pcSize){ + /* [out] */ ULONG *pcSize) override + { //ATLTRACE(_T("GetCodeInfo")); return m_pProfilerInfo->GetCodeInfo(functionId, pStart, pcSize); } virtual HRESULT STDMETHODCALLTYPE GetEventMask( - /* [out] */ DWORD *pdwEvents){ + /* [out] */ DWORD *pdwEvents) override + { //ATLTRACE(_T("GetEventMask")); return m_pProfilerInfo->GetEventMask(pdwEvents); } virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP( /* [in] */ LPCBYTE ip, - /* [out] */ FunctionID *pFunctionId){ + /* [out] */ FunctionID *pFunctionId) override + { //ATLTRACE(_T("GetFunctionFromIP")); return m_pProfilerInfo->GetFunctionFromIP(ip, pFunctionId); } @@ -61,21 +70,24 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, - /* [out] */ FunctionID *pFunctionId){ + /* [out] */ FunctionID *pFunctionId) override + { //ATLTRACE(_T("GetFunctionFromToken")); return m_pProfilerInfo->GetFunctionFromToken(moduleId, token, pFunctionId); } virtual HRESULT STDMETHODCALLTYPE GetHandleFromThread( /* [in] */ ThreadID threadId, - /* [out] */ HANDLE *phThread){ + /* [out] */ HANDLE *phThread) override + { //ATLTRACE(_T("GetHandleFromThread")); return m_pProfilerInfo->GetHandleFromThread(threadId, phThread); } virtual HRESULT STDMETHODCALLTYPE GetObjectSize( /* [in] */ ObjectID objectId, - /* [out] */ ULONG *pcSize){ + /* [out] */ ULONG *pcSize) override + { //ATLTRACE(_T("GetObjectSize")); return m_pProfilerInfo->GetObjectSize(objectId, pcSize); } @@ -84,20 +96,23 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, - /* [out] */ ULONG *pcRank){ + /* [out] */ ULONG *pcRank) override + { //ATLTRACE(_T("IsArrayClass")); return m_pProfilerInfo->IsArrayClass(classId, pBaseElemType, pBaseClassId, pcRank); } virtual HRESULT STDMETHODCALLTYPE GetThreadInfo( /* [in] */ ThreadID threadId, - /* [out] */ DWORD *pdwWin32ThreadId){ + /* [out] */ DWORD *pdwWin32ThreadId) override + { //ATLTRACE(_T("GetThreadInfo")); return m_pProfilerInfo->GetThreadInfo(threadId, pdwWin32ThreadId); } virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( - /* [out] */ ThreadID *pThreadId){ + /* [out] */ ThreadID *pThreadId) override + { //ATLTRACE(_T("GetCurrentThreadID")); return m_pProfilerInfo->GetCurrentThreadID(pThreadId); } @@ -105,7 +120,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo( /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, - /* [out] */ mdTypeDef *pTypeDefToken){ + /* [out] */ mdTypeDef *pTypeDefToken) override + { //ATLTRACE(_T("GetClassIDInfo")); return m_pProfilerInfo->GetClassIDInfo(classId, pModuleId, pTypeDefToken); } @@ -114,13 +130,15 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, - /* [out] */ mdToken *pToken){ + /* [out] */ mdToken *pToken) override + { //ATLTRACE(_T("GetFunctionInfo")); return m_pProfilerInfo->GetFunctionInfo(functionId, pClassId, pModuleId, pToken); } virtual HRESULT STDMETHODCALLTYPE SetEventMask( - /* [in] */ DWORD dwEvents){ + /* [in] */ DWORD dwEvents) override + { ATLTRACE(_T("CProfilerInfoBase::SetEventMask(0x%X)"), dwEvents); return m_pProfilerInfo->SetEventMask(dwEvents); } @@ -128,13 +146,15 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks( /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, - /* [in] */ FunctionTailcall *pFuncTailcall){ + /* [in] */ FunctionTailcall *pFuncTailcall) override + { //ATLTRACE(_T("SetEnterLeaveFunctionHooks")); return m_pProfilerInfo->SetEnterLeaveFunctionHooks(pFuncEnter, pFuncLeave, pFuncTailcall); } virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper( - /* [in] */ FunctionIDMapper *pFunc){ + /* [in] */ FunctionIDMapper *pFunc) override + { //ATLTRACE(_T("SetFunctionIDMapper")); return m_pProfilerInfo->SetFunctionIDMapper(pFunc); } @@ -143,7 +163,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, - /* [out] */ mdToken *pToken){ + /* [out] */ mdToken *pToken) override + { //ATLTRACE(_T("GetTokenAndMetaDataFromFunction")); return m_pProfilerInfo->GetTokenAndMetaDataFromFunction(functionId, riid, ppImport, pToken); } @@ -155,7 +176,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[], - /* [out] */ AssemblyID *pAssemblyId){ + /* [out] */ AssemblyID *pAssemblyId) override + { //ATLTRACE(_T("GetModuleInfo")); return m_pProfilerInfo->GetModuleInfo(moduleId, ppBaseLoadAddress, cchName, pcchName, szName, pAssemblyId); } @@ -164,7 +186,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, - /* [out] */ IUnknown **ppOut){ + /* [out] */ IUnknown **ppOut) override + { //ATLTRACE(_T("GetModuleMetaData")); return m_pProfilerInfo->GetModuleMetaData(moduleId, dwOpenFlags, riid, ppOut); } @@ -173,14 +196,16 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, - /* [out] */ ULONG *pcbMethodSize){ + /* [out] */ ULONG *pcbMethodSize) override + { //ATLTRACE(_T("GetILFunctionBody")); return m_pProfilerInfo->GetILFunctionBody(moduleId, methodId, ppMethodHeader, pcbMethodSize); } virtual HRESULT STDMETHODCALLTYPE GetILFunctionBodyAllocator( /* [in] */ ModuleID moduleId, - /* [out] */ IMethodMalloc **ppMalloc){ + /* [out] */ IMethodMalloc **ppMalloc) override + { //ATLTRACE(_T("GetILFunctionBodyAllocator")); return m_pProfilerInfo->GetILFunctionBodyAllocator(moduleId, ppMalloc); } @@ -188,7 +213,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, - /* [in] */ LPCBYTE pbNewILMethodHeader){ + /* [in] */ LPCBYTE pbNewILMethodHeader) override + { //ATLTRACE(_T("SetILFunctionBody")); return m_pProfilerInfo->SetILFunctionBody(moduleId, methodid, pbNewILMethodHeader); } @@ -199,7 +225,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[], - /* [out] */ ProcessID *pProcessId){ + /* [out] */ ProcessID *pProcessId) override + { //ATLTRACE(_T("GetAppDomainInfo")); return m_pProfilerInfo->GetAppDomainInfo(appDomainId, cchName, pcchName, szName, pProcessId); } @@ -211,18 +238,21 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[], /* [out] */ AppDomainID *pAppDomainId, - /* [out] */ ModuleID *pModuleId){ + /* [out] */ ModuleID *pModuleId) override + { //ATLTRACE(_T("GetAssemblyInfo")); return m_pProfilerInfo->GetAssemblyInfo(assemblyId, cchName, pcchName, szName, pAppDomainId, pModuleId); } virtual HRESULT STDMETHODCALLTYPE SetFunctionReJIT( - /* [in] */ FunctionID functionId){ + /* [in] */ FunctionID functionId) override + { //ATLTRACE(_T("SetFunctionReJIT")); return m_pProfilerInfo->SetFunctionReJIT(functionId); } - virtual HRESULT STDMETHODCALLTYPE ForceGC(void){ + virtual HRESULT STDMETHODCALLTYPE ForceGC(void) override + { //ATLTRACE(_T("GetClassFromObject")); return m_pProfilerInfo->ForceGC(); } @@ -231,39 +261,45 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, - /* [size_is][in] */ COR_IL_MAP rgILMapEntries[]){ + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[]) override + { //ATLTRACE(_T("SetILInstrumentedCodeMap")); return m_pProfilerInfo->SetILInstrumentedCodeMap(functionId, fStartJit, cILMapEntries, rgILMapEntries); } virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionInterface( - /* [out] */ IUnknown **ppicd){ + /* [out] */ IUnknown **ppicd) override + { //ATLTRACE(_T("GetInprocInspectionInterface")); return m_pProfilerInfo->GetInprocInspectionInterface(ppicd); } virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionIThisThread( - /* [out] */ IUnknown **ppicd){ + /* [out] */ IUnknown **ppicd) override + { //ATLTRACE(_T("GetInprocInspectionIThisThread")); return m_pProfilerInfo->GetInprocInspectionIThisThread(ppicd); } virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ThreadID threadId, - /* [out] */ ContextID *pContextId){ + /* [out] */ ContextID *pContextId) override + { //ATLTRACE(_T("GetThreadContext")); return m_pProfilerInfo->GetThreadContext(threadId, pContextId); } virtual HRESULT STDMETHODCALLTYPE BeginInprocDebugging( /* [in] */ BOOL fThisThreadOnly, - /* [out] */ DWORD *pdwProfilerContext){ + /* [out] */ DWORD *pdwProfilerContext) override + { //ATLTRACE(_T("BeginInprocDebugging")); return m_pProfilerInfo->BeginInprocDebugging(fThisThreadOnly, pdwProfilerContext); } virtual HRESULT STDMETHODCALLTYPE EndInprocDebugging( - /* [in] */ DWORD dwProfilerContext){ + /* [in] */ DWORD dwProfilerContext) override + { //ATLTRACE(_T("EndInprocDebugging")); return m_pProfilerInfo->EndInprocDebugging(dwProfilerContext); } @@ -272,7 +308,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, - /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[]){ + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[]) override + { //ATLTRACE(_T("GetILToNativeMapping")); return m_pProfilerInfo->GetILToNativeMapping(functionId, cMap, pcMap, map); } @@ -284,7 +321,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[], - /* [in] */ ULONG32 contextSize){ + /* [in] */ ULONG32 contextSize) override + { //ATLTRACE(_T("DoStackSnapshot")); return m_pProfilerInfo2->DoStackSnapshot(thread, callback, infoFlags, clientData, context, contextSize); } @@ -292,7 +330,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks2( /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, - /* [in] */ FunctionTailcall2 *pFuncTailcall){ + /* [in] */ FunctionTailcall2 *pFuncTailcall) override + { //ATLTRACE(_T("SetEnterLeaveFunctionHooks2")); return m_pProfilerInfo2->SetEnterLeaveFunctionHooks2(pFuncEnter, pFuncLeave, pFuncTailcall); } @@ -305,7 +344,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, - /* [out] */ ClassID typeArgs[]){ + /* [out] */ ClassID typeArgs[]) override + { //ATLTRACE(_T("GetFunctionInfo2")); return m_pProfilerInfo2->GetFunctionInfo2(funcId, frameInfo, pClassId, pModuleId, pToken, cTypeArgs, pcTypeArgs, typeArgs); } @@ -313,7 +353,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetStringLayout( /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, - /* [out] */ ULONG *pBufferOffset){ + /* [out] */ ULONG *pBufferOffset) override + { //ATLTRACE(_T("GetStringLayout")); return m_pProfilerInfo2->GetStringLayout(pBufferLengthOffset, pStringLengthOffset, pBufferOffset); } @@ -323,7 +364,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, - /* [out] */ ULONG *pulClassSize){ + /* [out] */ ULONG *pulClassSize) override + { //ATLTRACE(_T("GetClassLayout")); return m_pProfilerInfo2->GetClassLayout(classID, rFieldOffset, cFieldOffset, pcFieldOffset, pulClassSize); } @@ -335,7 +377,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, - /* [out] */ ClassID typeArgs[]){ + /* [out] */ ClassID typeArgs[]) override + { //ATLTRACE(_T("GetClassIDInfo2")); return m_pProfilerInfo2->GetClassIDInfo2(classId, pModuleId, pTypeDefToken, pParentClassId, cNumTypeArgs, pcNumTypeArgs, typeArgs); } @@ -344,7 +387,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, - /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[]){ + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[]) override + { //ATLTRACE(_T("GetCodeInfo2")); return m_pProfilerInfo2->GetCodeInfo2(functionID, cCodeInfos, pcCodeInfos, codeInfos); } @@ -354,7 +398,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[], - /* [out] */ ClassID *pClassID){ + /* [out] */ ClassID *pClassID) override + { //ATLTRACE(_T("GetClassFromTokenAndTypeArgs")); return m_pProfilerInfo2->GetClassFromTokenAndTypeArgs(moduleID, typeDef, cTypeArgs, typeArgs, pClassID); } @@ -365,14 +410,16 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[], - /* [out] */ FunctionID *pFunctionID){ + /* [out] */ FunctionID *pFunctionID) override + { //ATLTRACE(_T("GetFunctionFromTokenAndTypeArgs")); return m_pProfilerInfo2->GetFunctionFromTokenAndTypeArgs(moduleID, funcDef, classId, cTypeArgs, typeArgs, pFunctionID); } virtual HRESULT STDMETHODCALLTYPE EnumModuleFrozenObjects( /* [in] */ ModuleID moduleID, - /* [out] */ ICorProfilerObjectEnum **ppEnum){ + /* [out] */ ICorProfilerObjectEnum **ppEnum) override + { //ATLTRACE(_T("GetClassFromObject")); return m_pProfilerInfo2->EnumModuleFrozenObjects(moduleID, ppEnum); } @@ -382,21 +429,24 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[], /* [size_is][out] */ int pDimensionLowerBounds[], - /* [out] */ BYTE **ppData){ + /* [out] */ BYTE **ppData) override + { //ATLTRACE(_T("GetArrayObjectInfo")); return m_pProfilerInfo2->GetArrayObjectInfo(objectId, cDimensions, pDimensionSizes, pDimensionLowerBounds, ppData); } virtual HRESULT STDMETHODCALLTYPE GetBoxClassLayout( /* [in] */ ClassID classId, - /* [out] */ ULONG32 *pBufferOffset){ + /* [out] */ ULONG32 *pBufferOffset) override + { //ATLTRACE(_T("GetBoxClassLayout")); return m_pProfilerInfo2->GetBoxClassLayout(classId, pBufferOffset); } virtual HRESULT STDMETHODCALLTYPE GetThreadAppDomain( /* [in] */ ThreadID threadId, - /* [out] */ AppDomainID *pAppDomainId){ + /* [out] */ AppDomainID *pAppDomainId) override + { //ATLTRACE(_T("GetThreadAppDomain")); return m_pProfilerInfo2->GetThreadAppDomain(threadId, pAppDomainId); } @@ -404,7 +454,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetRVAStaticAddress( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, - /* [out] */ void **ppAddress){ + /* [out] */ void **ppAddress) override + { //ATLTRACE(_T("GetRVAStaticAddress")); return m_pProfilerInfo2->GetRVAStaticAddress(classId, fieldToken, ppAddress); } @@ -413,7 +464,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, - /* [out] */ void **ppAddress){ + /* [out] */ void **ppAddress) override + { //ATLTRACE(_T("GetAppDomainStaticAddress")); return m_pProfilerInfo2->GetAppDomainStaticAddress(classId, fieldToken, appDomainId, ppAddress); } @@ -422,7 +474,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, - /* [out] */ void **ppAddress){ + /* [out] */ void **ppAddress) override + { //ATLTRACE(_T("GetThreadStaticAddress")); return m_pProfilerInfo2->GetThreadStaticAddress(classId, fieldToken, threadId, ppAddress); } @@ -431,7 +484,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, - /* [out] */ void **ppAddress){ + /* [out] */ void **ppAddress) override + { //ATLTRACE(_T("GetContextStaticAddress")); return m_pProfilerInfo2->GetContextStaticAddress(classId, fieldToken, contextId, ppAddress); } @@ -439,7 +493,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetStaticFieldInfo( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, - /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo){ + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo) override + { //ATLTRACE(_T("GetStaticFieldInfo")); return m_pProfilerInfo2->GetStaticFieldInfo(classId, fieldToken, pFieldInfo); } @@ -447,47 +502,54 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetGenerationBounds( /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, - /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[]){ + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[]) override + { //ATLTRACE(_T("GetGenerationBounds")); return m_pProfilerInfo2->GetGenerationBounds(cObjectRanges, pcObjectRanges, ranges); } virtual HRESULT STDMETHODCALLTYPE GetObjectGeneration( /* [in] */ ObjectID objectId, - /* [out] */ COR_PRF_GC_GENERATION_RANGE *range){ + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range) override + { //ATLTRACE(_T("GetObjectGeneration")); return m_pProfilerInfo2->GetObjectGeneration(objectId, range); } virtual HRESULT STDMETHODCALLTYPE GetNotifiedExceptionClauseInfo( - /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo){ + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo) override + { //ATLTRACE(_T("GetNotifiedExceptionClauseInfo")); return m_pProfilerInfo2->GetNotifiedExceptionClauseInfo(pinfo); } public: // ICorProfilerInfo3 virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions( - /* [out] */ ICorProfilerFunctionEnum **ppEnum){ + /* [out] */ ICorProfilerFunctionEnum **ppEnum) override + { //ATLTRACE(_T("EnumJITedFunctions")); return m_pProfilerInfo3->EnumJITedFunctions(ppEnum); } virtual HRESULT STDMETHODCALLTYPE RequestProfilerDetach( - /* [in] */ DWORD dwExpectedCompletionMilliseconds){ + /* [in] */ DWORD dwExpectedCompletionMilliseconds) override + { //ATLTRACE(_T("RequestProfilerDetach")); return m_pProfilerInfo3->RequestProfilerDetach(dwExpectedCompletionMilliseconds); } virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper2( /* [in] */ FunctionIDMapper2 *pFunc, - /* [in] */ void *clientData){ + /* [in] */ void *clientData) override + { //ATLTRACE(_T("SetFunctionIDMapper2")); return m_pProfilerInfo3->SetFunctionIDMapper2(pFunc, clientData); } virtual HRESULT STDMETHODCALLTYPE GetStringLayout2( /* [out] */ ULONG *pStringLengthOffset, - /* [out] */ ULONG *pBufferOffset){ + /* [out] */ ULONG *pBufferOffset) override + { //ATLTRACE(_T("GetStringLayout2")); return m_pProfilerInfo3->GetStringLayout2(pStringLengthOffset, pBufferOffset); } @@ -495,7 +557,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3( /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, - /* [in] */ FunctionTailcall3 *pFuncTailcall3){ + /* [in] */ FunctionTailcall3 *pFuncTailcall3) override + { //ATLTRACE(_T("SetEnterLeaveFunctionHooks3")); return m_pProfilerInfo3->SetEnterLeaveFunctionHooks3(pFuncEnter3, pFuncLeave3, pFuncTailcall3); } @@ -503,7 +566,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3WithInfo( /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, - /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo){ + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo) override + { //ATLTRACE(_T("SetEnterLeaveFunctionHooks3WithInfo")); return m_pProfilerInfo3->SetEnterLeaveFunctionHooks3WithInfo(pFuncEnter3WithInfo, pFuncLeave3WithInfo, pFuncTailcall3WithInfo); } @@ -513,7 +577,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, - /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo){ + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo) override + { //ATLTRACE(_T("GetFunctionEnter3Info")); return m_pProfilerInfo3->GetFunctionEnter3Info(functionId, eltInfo, pFrameInfo, pcbArgumentInfo, pArgumentInfo); } @@ -522,7 +587,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, - /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange){ + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange) override + { //ATLTRACE(_T("GetFunctionLeave3Info")); return m_pProfilerInfo3->GetFunctionLeave3Info(functionId, eltInfo, pFrameInfo, pRetvalRange); } @@ -530,13 +596,15 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetFunctionTailcall3Info( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, - /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo){ + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo) override + { //ATLTRACE(_T("GetFunctionTailcall3Info")); return m_pProfilerInfo3->GetFunctionTailcall3Info(functionId, eltInfo, pFrameInfo); } virtual HRESULT STDMETHODCALLTYPE EnumModules( - /* [out] */ ICorProfilerModuleEnum **ppEnum){ + /* [out] */ ICorProfilerModuleEnum **ppEnum) override + { //ATLTRACE(_T("EnumModules")); return m_pProfilerInfo3->EnumModules(ppEnum); } @@ -551,7 +619,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ - _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[]){ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[]) override + { //ATLTRACE(_T("GetRuntimeInformation")); return m_pProfilerInfo3->GetRuntimeInformation(pClrInstanceId, pRuntimeType, pMajorVersion, pMinorVersion, pBuildNumber, pQFEVersion, cchVersionString, pcchVersionString, szVersionString); @@ -562,7 +631,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, - /* [out] */ void **ppAddress){ + /* [out] */ void **ppAddress) override + { //ATLTRACE(_T("GetThreadStaticAddress2")); return m_pProfilerInfo3->GetThreadStaticAddress2(classId, fieldToken, appDomainId, threadId, ppAddress); @@ -572,7 +642,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, - /* [length_is][size_is][out] */ AppDomainID appDomainIds[]){ + /* [length_is][size_is][out] */ AppDomainID appDomainIds[]) override + { //ATLTRACE(_T("GetAppDomainsContainingModule")); return m_pProfilerInfo3->GetAppDomainsContainingModule(moduleId, cAppDomainIds, pcAppDomainIds, appDomainIds); @@ -586,7 +657,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[], /* [out] */ AssemblyID *pAssemblyId, - /* [out] */ DWORD *pdwModuleFlags){ + /* [out] */ DWORD *pdwModuleFlags) override + { //ATLTRACE(_T("GetModuleInfo2")); return m_pProfilerInfo3->GetModuleInfo2(moduleId, ppBaseLoadAddress, cchName, pcchName, szName, pAssemblyId, pdwModuleFlags); @@ -594,12 +666,14 @@ class CProfilerInfoBase : public ICorProfilerInfo4 public: // ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE EnumThreads( - /* [out] */ ICorProfilerThreadEnum **ppEnum){ + /* [out] */ ICorProfilerThreadEnum **ppEnum) override + { //ATLTRACE(_T("EnumThreads")); return m_pProfilerInfo4->EnumThreads(ppEnum); } - virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread(void){ + virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread(void) override + { //ATLTRACE(_T("InitializeCurrentThread")); return m_pProfilerInfo4->InitializeCurrentThread(); } @@ -607,7 +681,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE RequestReJIT( /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[], - /* [size_is][in] */ mdMethodDef methodIds[]){ + /* [size_is][in] */ mdMethodDef methodIds[]) override + { //ATLTRACE(_T("RequestReJIT")); return m_pProfilerInfo4->RequestReJIT(cFunctions, moduleIds, methodIds); } @@ -616,7 +691,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[], /* [size_is][in] */ mdMethodDef methodIds[], - /* [size_is][out] */ HRESULT status[]){ + /* [size_is][out] */ HRESULT status[]) override + { //ATLTRACE(_T("RequestRevert")); return m_pProfilerInfo4->RequestRevert(cFunctions, moduleIds, methodIds, status); } @@ -626,7 +702,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, - /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[]){ + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[]) override + { //ATLTRACE(_T("GetCodeInfo3")); return m_pProfilerInfo4->GetCodeInfo3(functionID, reJitId, cCodeInfos, pcCodeInfos, codeInfos); } @@ -634,7 +711,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP2( /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, - /* [out] */ ReJITID *pReJitId){ + /* [out] */ ReJITID *pReJitId) override + { //ATLTRACE(_T("GetFunctionFromIP2")); return m_pProfilerInfo4->GetFunctionFromIP2(ip, pFunctionId, pReJitId); } @@ -643,7 +721,8 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, - /* [length_is][size_is][out] */ ReJITID reJitIds[]){ + /* [length_is][size_is][out] */ ReJITID reJitIds[]) override + { //ATLTRACE(_T("GetClassFromObject")); return m_pProfilerInfo4->GetReJITIDs(functionId, cReJitIds, pcReJitIds, reJitIds); } @@ -653,20 +732,23 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, - /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[]){ + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[]) override + { //ATLTRACE(_T("GetILToNativeMapping2")); return m_pProfilerInfo4->GetILToNativeMapping2(functionId, reJitId, cMap, pcMap, map); } virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions2( - /* [out] */ ICorProfilerFunctionEnum **ppEnum){ + /* [out] */ ICorProfilerFunctionEnum **ppEnum) override + { //ATLTRACE(_T("EnumJITedFunctions2")); return m_pProfilerInfo4->EnumJITedFunctions2(ppEnum); } virtual HRESULT STDMETHODCALLTYPE GetObjectSize2( /* [in] */ ObjectID objectId, - /* [out] */ SIZE_T *pcSize){ + /* [out] */ SIZE_T *pcSize) override + { //ATLTRACE(_T("GetObjectSize2")); return m_pProfilerInfo4->GetObjectSize2(objectId, pcSize); } diff --git a/main/OpenCover.Profiler/SharedMemory.cpp b/main/OpenCover.Profiler/SharedMemory.cpp index 8d8fe5189..07f792741 100644 --- a/main/OpenCover.Profiler/SharedMemory.cpp +++ b/main/OpenCover.Profiler/SharedMemory.cpp @@ -12,13 +12,13 @@ CSharedMemory::~CSharedMemory() { } void CSharedMemory::CloseMapping() { - if (m_hMemory != NULL) { - for (auto it = m_viewMap.begin(); it != m_viewMap.end(); it++) { + if (m_hMemory != nullptr) { + for (auto it = m_viewMap.begin(); it != m_viewMap.end(); ++it) { ::UnmapViewOfFile((*it).first); } m_viewMap.clear(); CloseHandle(m_hMemory); - m_hMemory = NULL; + m_hMemory = nullptr; } } @@ -29,7 +29,7 @@ void CSharedMemory::OpenFileMapping(const TCHAR* pName) { void* CSharedMemory::MapViewOfFile(DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) { if (!IsValid()) { - return NULL; + return nullptr; } void* pMappedData = ::MapViewOfFile( m_hMemory, @@ -39,14 +39,14 @@ void* CSharedMemory::MapViewOfFile(DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow dwNumberOfBytesToMap ); - if (pMappedData != NULL) { + if (pMappedData != nullptr) { m_viewMap.push_back(std::pair(pMappedData, dwNumberOfBytesToMap)); } return pMappedData; } void CSharedMemory::FlushViewOfFile() { - for (auto it = m_viewMap.begin(); it != m_viewMap.end(); it++) { + for (auto it = m_viewMap.begin(); it != m_viewMap.end(); ++it) { ::FlushViewOfFile((*it).first, (*it).second); } } diff --git a/main/OpenCover.Profiler/SharedMemory.h b/main/OpenCover.Profiler/SharedMemory.h index f4ff0a2f0..a91394d92 100644 --- a/main/OpenCover.Profiler/SharedMemory.h +++ b/main/OpenCover.Profiler/SharedMemory.h @@ -8,14 +8,14 @@ class CSharedMemory { public: - CSharedMemory() : m_hMemory(NULL) { } + CSharedMemory() : m_hMemory(nullptr) { } ~CSharedMemory(); public: void OpenFileMapping(const TCHAR *pName); void* MapViewOfFile(DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap); static DWORD GetAllocationGranularity(); - bool IsValid() {return m_hMemory!=NULL; } + bool IsValid() { return m_hMemory != nullptr; } void FlushViewOfFile(); private: diff --git a/main/OpenCover.Profiler/Synchronization.h b/main/OpenCover.Profiler/Synchronization.h index c2022712c..0d8ef6c4d 100644 --- a/main/OpenCover.Profiler/Synchronization.h +++ b/main/OpenCover.Profiler/Synchronization.h @@ -10,38 +10,38 @@ class CMutex { public: - CMutex() : m_hMutex(NULL) {} + CMutex() : m_hMutex(nullptr) {} ~CMutex() { CloseHandle(); } - bool IsValid() {return m_hMutex!=NULL; } + bool IsValid() { return m_hMutex != nullptr; } public: - void Initialise(const TCHAR * pName) { CloseHandle(); m_hMutex = ::CreateMutex(NULL, false, pName); } - void Enter(){ if (m_hMutex!=NULL) { ::WaitForSingleObject(m_hMutex, INFINITE);} } - void Leave(){ if (m_hMutex!=NULL) { ::ReleaseMutex(m_hMutex);} } + void Initialise(const TCHAR * pName) { CloseHandle(); m_hMutex = ::CreateMutex(nullptr, false, pName); } + void Enter(){ if (m_hMutex != nullptr) { ::WaitForSingleObject(m_hMutex, INFINITE); } } + void Leave(){ if (m_hMutex != nullptr) { ::ReleaseMutex(m_hMutex); } } private: HANDLE m_hMutex; - void CloseHandle() {if (m_hMutex!=NULL) { ::CloseHandle(m_hMutex); m_hMutex=NULL; }} + void CloseHandle() { if (m_hMutex != nullptr) { ::CloseHandle(m_hMutex); m_hMutex = nullptr; } } }; class CSemaphore { public: - CSemaphore() : m_hSemaphore(NULL) {} + CSemaphore() : m_hSemaphore(nullptr) {} ~CSemaphore() { CloseHandle(); } - bool IsValid() { return m_hSemaphore != NULL; } + bool IsValid() { return m_hSemaphore != nullptr; } public: - void Initialise(const TCHAR * pName) { CloseHandle(); m_hSemaphore = ::CreateSemaphore(NULL, 0, 2, pName); _handleName = pName; } + void Initialise(const TCHAR * pName) { CloseHandle(); m_hSemaphore = ::CreateSemaphore(nullptr, 0, 2, pName); _handleName = pName; } void Enter(){ if (IsValid()) { ::WaitForSingleObject(m_hSemaphore, INFINITE); } } - void Leave(){ if (IsValid()) { ::ReleaseSemaphore(m_hSemaphore, 1, NULL); } } + void Leave(){ if (IsValid()) { ::ReleaseSemaphore(m_hSemaphore, 1, nullptr); } } protected: HANDLE m_hSemaphore; tstring _handleName; private: - void CloseHandle() { if (IsValid()) { ::CloseHandle(m_hSemaphore); m_hSemaphore = NULL; } } + void CloseHandle() { if (IsValid()) { ::CloseHandle(m_hSemaphore); m_hSemaphore = nullptr; } } }; class CSemaphoreEx : public CSemaphore { @@ -78,12 +78,12 @@ class CScopedLock class CEvent { public: - CEvent () : m_hEvent(NULL) { } + CEvent() : m_hEvent(nullptr) { } ~CEvent() { CloseHandle(); } - bool IsValid() {return m_hEvent!=NULL; } + bool IsValid() { return m_hEvent != nullptr; } public: - void Initialise(const TCHAR * pName, BOOL bManualReset = TRUE) { CloseHandle(); m_hEvent = ::CreateEvent(NULL, bManualReset, FALSE, pName); } + void Initialise(const TCHAR * pName, BOOL bManualReset = TRUE) { CloseHandle(); m_hEvent = ::CreateEvent(nullptr, bManualReset, FALSE, pName); } void Set() { ::SetEvent(m_hEvent); } void Wait() { ::WaitForSingleObject(m_hEvent, INFINITE); } @@ -92,6 +92,6 @@ class CEvent private: HANDLE m_hEvent; - void CloseHandle() {if (m_hEvent!= NULL) { ::CloseHandle(m_hEvent); m_hEvent = NULL; }} + void CloseHandle() { if (m_hEvent != nullptr) { ::CloseHandle(m_hEvent); m_hEvent = nullptr; } } }; From 7ad7e076f0c1850d8e608189ec6fec4c76219f6a Mon Sep 17 00:00:00 2001 From: sawilde Date: Wed, 23 Sep 2015 06:01:55 +1000 Subject: [PATCH 03/41] update wix installer to include symbols by default - improve crash reporting --- main/OpenCover.Installer/Components.wxs | 16 +++++----------- main/OpenCover.Installer/Product.wxs | 11 ++--------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/main/OpenCover.Installer/Components.wxs b/main/OpenCover.Installer/Components.wxs index 5eeece707..1f848c134 100644 --- a/main/OpenCover.Installer/Components.wxs +++ b/main/OpenCover.Installer/Components.wxs @@ -16,12 +16,15 @@ + + + @@ -43,11 +46,6 @@ - - - - - @@ -87,9 +85,7 @@ --> - - - + @@ -105,9 +101,7 @@ --> - - - + diff --git a/main/OpenCover.Installer/Product.wxs b/main/OpenCover.Installer/Product.wxs index c8de0522f..121b8d6d2 100644 --- a/main/OpenCover.Installer/Product.wxs +++ b/main/OpenCover.Installer/Product.wxs @@ -56,20 +56,13 @@ + + - - - - - - - - - From ec4683278c45479504bdfecf32769e0413a82d98 Mon Sep 17 00:00:00 2001 From: sawilde Date: Sun, 27 Sep 2015 12:28:51 +1000 Subject: [PATCH 04/41] prep for talk --- main/OpenCover.Framework/Manager/ProfilerManager.cs | 2 ++ .../Framework/Manager/ProfilerManagerTests.cs | 8 ++++---- main/cmdline/dogfood.cmd | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index 545776677..e8a8e5d72 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -127,6 +127,8 @@ private void SetProfilerAttributesOnDictionary(string profilerKey, string profil dictionary["Cor_Enable_Profiling"] = "1"; dictionary["CoreClr_Profiler"] = ProfilerGuid; dictionary["CoreClr_Enable_Profiling"] = "1"; + dictionary["Cor_Profiler_Path"] = string.Empty; + dictionary["CorClr_Profiler_Path"] = string.Empty; switch (_commandLine.Registration) { diff --git a/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs b/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs index 999053948..e7c593333 100644 --- a/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs +++ b/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs @@ -146,8 +146,8 @@ public void Manager_DoesNotAdd_Cor_Profiler_Path_EnvironmentVariable_WithNormalR RunSimpleProcess(dict); // assert - Assert.IsFalse(dict.ContainsKey(@"Cor_Profiler_Path")); - Assert.IsFalse(dict.ContainsKey(@"CorClr_Profiler_Path")); + Assert.IsFalse(!(dict.ContainsKey(@"Cor_Profiler_Path") || !string.IsNullOrEmpty(dict[@"Cor_Profiler_Path"]))); + Assert.IsFalse(!(dict.ContainsKey(@"CorClr_Profiler_Path") || !string.IsNullOrEmpty(dict[@"CorClr_Profiler_Path"]))); } [Test] @@ -161,8 +161,8 @@ public void Manager_DoesNotAdd_Cor_Profiler_Path_EnvironmentVariable_WithUserReg RunSimpleProcess(dict); // assert - Assert.IsFalse(dict.ContainsKey(@"Cor_Profiler_Path")); - Assert.IsFalse(dict.ContainsKey(@"CorClr_Profiler_Path")); + Assert.IsFalse(!(dict.ContainsKey(@"Cor_Profiler_Path") || !string.IsNullOrEmpty(dict[@"Cor_Profiler_Path"]))); + Assert.IsFalse(!(dict.ContainsKey(@"CorClr_Profiler_Path") || !string.IsNullOrEmpty(dict[@"CorClr_Profiler_Path"]))); } [Test] diff --git a/main/cmdline/dogfood.cmd b/main/cmdline/dogfood.cmd index 7d00a3c70..17ec381f5 100644 --- a/main/cmdline/dogfood.cmd +++ b/main/cmdline/dogfood.cmd @@ -1 +1,4 @@ +pushd %cd% +cd %~dp0 OpenCover.Console.exe -register:user -target:..\..\..\main\packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -targetargs:"OpenCover.Test.dll /noshadow /exclude:AdminOnly" -filter:"+[Open*]* -[OpenCover.T*]* -{nunit-console*}[*]* -{pdb*}[*]*" -output:opencovertests.xml +popd \ No newline at end of file From 17983aea46085bf2d498de5fec0b06246bf072d5 Mon Sep 17 00:00:00 2001 From: sawilde Date: Sun, 8 Nov 2015 15:59:35 +1100 Subject: [PATCH 05/41] housekeeping --- main/OpenCover.Console/Program.cs | 4 +- main/OpenCover.Framework/Bootstrapper.cs | 4 + .../Communication/CommunicationManager.cs | 15 +++- .../Communication/MarshalWapper.cs | 13 ++++ .../Communication/MessageHandler.cs | 14 ++++ .../Communication/Messages.cs | 10 ++- main/OpenCover.Framework/Filter.cs | 73 ++++++++++++++++++- .../Manager/MemoryManager.cs | 10 ++- .../Manager/ProfilerManager.cs | 27 ++++++- main/OpenCover.Framework/Model/Class.cs | 4 + main/OpenCover.Framework/Model/File.cs | 4 +- .../InstrumentationModelBuilderFactory.cs | 6 ++ main/OpenCover.Framework/Model/Method.cs | 6 +- main/OpenCover.Framework/Model/Module.cs | 8 +- .../Model/SequencePoint.cs | 6 ++ .../Model/SkippedEntity.cs | 8 +- .../Model/SummarySkippedEntity.cs | 3 + .../Model/TrackedMethod.cs | 4 +- .../Persistance/BasePersistance.cs | 3 + .../Persistance/FilePersistance.cs | 3 + .../Strategy/TrackedMethodStrategyManager.cs | 10 +++ .../Utility/PerfCounters.cs | 23 +++++- 22 files changed, 232 insertions(+), 26 deletions(-) diff --git a/main/OpenCover.Console/Program.cs b/main/OpenCover.Console/Program.cs index e87483d16..1a23ecfac 100644 --- a/main/OpenCover.Console/Program.cs +++ b/main/OpenCover.Console/Program.cs @@ -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 :("); } @@ -303,7 +303,7 @@ private static void RunService(CommandLineParser parser, Action + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 public void Dispose() { if (_container == null) return; diff --git a/main/OpenCover.Framework/Communication/CommunicationManager.cs b/main/OpenCover.Framework/Communication/CommunicationManager.cs index c737ae9e7..b2b1dce5b 100644 --- a/main/OpenCover.Framework/Communication/CommunicationManager.cs +++ b/main/OpenCover.Framework/Communication/CommunicationManager.cs @@ -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 { @@ -48,6 +45,11 @@ public CommunicationManager(IMessageHandler messageHandler) _messageHandler = messageHandler; } + /// + /// Process a communication related message from a profiler + /// + /// + /// public void HandleCommunicationBlock(IManagedCommunicationBlock mcb, Action offloadHandling) { mcb.ProfilerRequestsInformation.Reset(); @@ -71,6 +73,10 @@ private static void SendChunkAndWaitForConfirmation(int writeSize, IManagedCommu mcb.InformationReadByProfiler.Reset(); } + /// + /// process a results block from the profiler + /// + /// public byte[] HandleMemoryBlock(IManagedMemoryBlock mmb) { mmb.ProfilerHasResults.Reset(); @@ -88,6 +94,9 @@ public byte[] HandleMemoryBlock(IManagedMemoryBlock mmb) return newData; } + /// + /// Communication is over + /// public void Complete() { _messageHandler.Complete(); diff --git a/main/OpenCover.Framework/Communication/MarshalWapper.cs b/main/OpenCover.Framework/Communication/MarshalWapper.cs index 1f4f71d33..1531b7000 100644 --- a/main/OpenCover.Framework/Communication/MarshalWapper.cs +++ b/main/OpenCover.Framework/Communication/MarshalWapper.cs @@ -39,11 +39,24 @@ public interface IMarshalWrapper /// public class MarshalWrapper : IMarshalWrapper { + /// + /// Map pinned memory to a structure + /// + /// The type of the structure + /// + /// public T PtrToStructure(IntPtr pinnedMemory) { return (T)Marshal.PtrToStructure(pinnedMemory, typeof(T)); } + /// + /// Map a structure to pinned memory + /// + /// + /// + /// + /// public void StructureToPtr(T structure, IntPtr pinnedMemory, bool fDeleteOld) { Marshal.StructureToPtr(structure, pinnedMemory, fDeleteOld); diff --git a/main/OpenCover.Framework/Communication/MessageHandler.cs b/main/OpenCover.Framework/Communication/MessageHandler.cs index 99f246257..d49a1152b 100644 --- a/main/OpenCover.Framework/Communication/MessageHandler.cs +++ b/main/OpenCover.Framework/Communication/MessageHandler.cs @@ -67,6 +67,14 @@ public MessageHandler(IProfilerCommunication profilerCommunication, IMarshalWrap _memoryManager = memoryManager; } + /// + /// Process a Standard Message + /// + /// + /// + /// + /// + /// public int StandardMessage(MSG_Type msgType, IManagedCommunicationBlock mcb, Action chunkReady, Action offloadHandling) { IntPtr pinnedMemory = mcb.PinnedDataCommunication.AddrOfPinnedObject(); @@ -319,6 +327,9 @@ private int HandleTrackProcessMessage(IntPtr pinnedMemory) private int _readSize; + /// + /// Maximum size of a base message + /// public int ReadSize { get @@ -344,6 +355,9 @@ public int ReadSize } } + /// + /// Finished + /// public void Complete() { _profilerCommunication.Stopping(); diff --git a/main/OpenCover.Framework/Communication/Messages.cs b/main/OpenCover.Framework/Communication/Messages.cs index ba1e40846..49c423669 100644 --- a/main/OpenCover.Framework/Communication/Messages.cs +++ b/main/OpenCover.Framework/Communication/Messages.cs @@ -10,7 +10,8 @@ namespace OpenCover.Framework.Communication /// /// The command supportd by the host /// -// ReSharper disable InconsistentNaming + // ReSharper disable InconsistentNaming + // ReSharper disable once EnumUnderlyingTypeIsInt public enum MSG_Type : int { /// @@ -338,8 +339,15 @@ public struct MSG_AllocateBuffer_Request [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MSG_AllocateBuffer_Response { + /// + /// is the buffer allocated + /// [MarshalAs(UnmanagedType.Bool)] public bool allocated; + + /// + /// The id assigned to the buffer + /// public uint bufferId; } diff --git a/main/OpenCover.Framework/Filter.cs b/main/OpenCover.Framework/Filter.cs index 1501cb276..5211ddd69 100644 --- a/main/OpenCover.Framework/Filter.cs +++ b/main/OpenCover.Framework/Filter.cs @@ -5,7 +5,6 @@ // using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -25,6 +24,10 @@ public class Filter : IFilter internal IList ExcludedAttributes { get; private set; } internal IList ExcludedFiles { get; private set; } internal IList TestFiles { get; private set; } + + /// + /// Are the filters supplied as reguar expressions + /// public bool RegExFilters { get; private set; } @@ -42,6 +45,13 @@ public Filter(bool useRegexFilters = false) RegExFilters = useRegexFilters; } + /// + /// Decides whether an assembly should be included in the instrumentation + /// + /// The name of the process being profiled + /// the name of the assembly under profile + /// 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 * public bool UseAssembly(string processName, string assemblyName) { processName = Path.GetFileNameWithoutExtension(processName); @@ -65,6 +75,13 @@ public bool UseAssembly(string processName, string assemblyName) return false; } + /// + /// Determine if an [assemblyname]classname pair matches the current Exclusion or Inclusion filters + /// + /// The name of the process + /// the name of the assembly under profile + /// the name of the class under profile + /// false - if pair matches the exclusion filter or matches no filters, true - if pair matches in the inclusion filter public bool InstrumentClass(string processName, string assemblyName, string className) { if (string.IsNullOrEmpty(processName) || string.IsNullOrEmpty(assemblyName) || string.IsNullOrEmpty(className)) @@ -96,11 +113,23 @@ public bool InstrumentClass(string processName, string assemblyName, string clas } + /// + /// Determine if an [assemblyname]classname pair matches the current Exclusion or Inclusion filters + /// + /// the name of the assembly under profile + /// the name of the class under profile + /// false - if pair matches the exclusion filter or matches no filters, true - if pair matches in the inclusion filter public bool InstrumentClass(string assemblyName, string className) { return InstrumentClass(Guid.NewGuid().ToString(), assemblyName, className); } + /// + /// Add a filter + /// + /// A filter is of the format (+ or -)[assemblyName]className, wildcards are allowed.
+ /// i.e. -[mscorlib], -[System.*]*, +[App.*]*, +[*]* + /// public void AddFilter(string assemblyClassName) { string assemblyName; @@ -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)); } + /// + /// Add attribute exclusion filters + /// + /// An array of filters that are used to wildcard match an attribute public void AddAttributeExclusionFilters(string[] exclusionFilters) { ExcludedAttributes.AddFilters(exclusionFilters, RegExFilters); } + /// + /// Is this entity (method/type) excluded due to an attributeFilter + /// + /// The entity to test + /// public bool ExcludeByAttribute(IMemberDefinition entity) { if (ExcludedAttributes.Count == 0) @@ -207,6 +245,11 @@ where excludeAttribute.IsMatchingExpression(customAttribute.AttributeType.FullNa select excludeAttribute).Any(); } + /// + /// Is this entity excluded due to an attributeFilter + /// + /// The entity to test + /// public bool ExcludeByAttribute(AssemblyDefinition entity) { if (ExcludedAttributes.Count == 0) @@ -215,6 +258,11 @@ public bool ExcludeByAttribute(AssemblyDefinition entity) return ExcludeByAttribute((ICustomAttributeProvider)entity); } + /// + /// Is this file excluded + /// + /// The name of the file to test + /// public bool ExcludeByFile(string fileName) { if (ExcludedFiles.Count == 0 || string.IsNullOrWhiteSpace(fileName)) @@ -223,11 +271,20 @@ public bool ExcludeByFile(string fileName) return ExcludedFiles.Any(excludeFile => excludeFile.IsMatchingExpression(fileName)); } + /// + /// Add file exclusion filters + /// + /// public void AddFileExclusionFilters(string[] exclusionFilters) { ExcludedFiles.AddFilters(exclusionFilters, RegExFilters); } + /// + /// Decides whether an assembly should be analysed for test methods + /// + /// the name of the assembly under profile + /// true - if the assembly matches the test assembly filter public bool UseTestAssembly(string assemblyName) { if (TestFiles.Count == 0 || string.IsNullOrWhiteSpace(assemblyName)) @@ -236,11 +293,20 @@ public bool UseTestAssembly(string assemblyName) return TestFiles.Any(file => file.IsMatchingExpression(assemblyName)); } + /// + /// Add test file filters + /// + /// public void AddTestFileFilters(string[] testFilters) { TestFiles.AddFilters(testFilters, RegExFilters); } + /// + /// Is the method an auto-implemented property get/set + /// + /// + /// public bool IsAutoImplementedProperty(MethodDefinition method) { if ((method.IsSetter || method.IsGetter) && method.HasCustomAttributes) @@ -250,6 +316,11 @@ public bool IsAutoImplementedProperty(MethodDefinition method) return false; } + /// + /// Should we instrument this asssembly + /// + /// + /// public bool InstrumentProcess(string processName) { if (string.IsNullOrEmpty(processName)) diff --git a/main/OpenCover.Framework/Manager/MemoryManager.cs b/main/OpenCover.Framework/Manager/MemoryManager.cs index c97604ef1..b034b849c 100644 --- a/main/OpenCover.Framework/Manager/MemoryManager.cs +++ b/main/OpenCover.Framework/Manager/MemoryManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.IO.MemoryMappedFiles; using System.Linq; @@ -28,7 +27,12 @@ public class MemoryManager : IMemoryManager ///
public class ManagedBlock { + /// + /// protected string Namespace; + + /// + /// protected string Key; /// @@ -343,6 +347,10 @@ public void RemoveDeactivatedBlocks() } } + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 public void Dispose() { lock (_lockObject) diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index e8a8e5d72..106ea3113 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -228,15 +228,22 @@ private void ProcessMessages(WaitHandle[] handles) .Select(g => g.Select(a => a.Pair).ToList()) .Select(g => Task.Factory.StartNew(() => { - g.Select(h => h.Item1).ToList().ForEach(h => h.Set()); - WaitHandle.WaitAll(g.Select(h => h.Item2).ToArray(), new TimeSpan(0, 0, 20)); + ConsumeException(() => + { + g.Select(h => h.Item1).ToList().ForEach(h => h.Set()); + WaitHandle.WaitAll(g.Select(h => h.Item2).ToArray(), new TimeSpan(0, 0, 20)); + }); })).ToArray(); Task.WaitAll(tasks); foreach (var threadHandle in threadHandles) { - threadHandle.Item1.Dispose(); - threadHandle.Item2.Dispose(); + var handle = threadHandle; + ConsumeException(() => + { + handle.Item1.Dispose(); + handle.Item2.Dispose(); + }); } threadHandles.Clear(); } @@ -245,6 +252,18 @@ private void ProcessMessages(WaitHandle[] handles) _messageQueue.Enqueue(new byte[0]); } + // wrap exceptions when closing down + private static void ConsumeException(Action doSomething) + { + try + { + doSomething(); + } + catch (Exception ex) + { + DebugLogger.Error("An unexpected exception was encountered but consumed.", ex); + } + } private Tuple StartProcessingThread(ManagedBufferBlock block) { DebugLogger.InfoFormat("Starting Process Block => {0}", block.BufferId); diff --git a/main/OpenCover.Framework/Model/Class.cs b/main/OpenCover.Framework/Model/Class.cs index c7df3e252..9e4167973 100644 --- a/main/OpenCover.Framework/Model/Class.cs +++ b/main/OpenCover.Framework/Model/Class.cs @@ -37,6 +37,10 @@ public Class() /// public Method[] Methods { get; set; } + /// + /// If a class was skipped by instrumentation, supply the reason why + /// + /// public override void MarkAsSkipped(SkippedMethod reason) { SkippedDueTo = reason; diff --git a/main/OpenCover.Framework/Model/File.cs b/main/OpenCover.Framework/Model/File.cs index b21492d84..002d94377 100644 --- a/main/OpenCover.Framework/Model/File.cs +++ b/main/OpenCover.Framework/Model/File.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Xml.Serialization; @@ -17,6 +16,9 @@ namespace OpenCover.Framework.Model /// public class FileRef { + /// + /// The uniqueid of a file in a coverage session + /// [XmlAttribute("uid")] public UInt32 UniqueId { get; set; } } diff --git a/main/OpenCover.Framework/Model/InstrumentationModelBuilderFactory.cs b/main/OpenCover.Framework/Model/InstrumentationModelBuilderFactory.cs index 160356ea9..470ab72e4 100644 --- a/main/OpenCover.Framework/Model/InstrumentationModelBuilderFactory.cs +++ b/main/OpenCover.Framework/Model/InstrumentationModelBuilderFactory.cs @@ -35,6 +35,12 @@ public InstrumentationModelBuilderFactory(ICommandLine commandLine, IFilter filt _trackedMethodStrategyManager = trackedMethodStrategyManager; } + /// + /// Create a Model Builder for a module + /// + /// + /// + /// public IInstrumentationModelBuilder CreateModelBuilder(string modulePath, string moduleName) { var manager = new CecilSymbolManager(_commandLine, _filter, _logger, _trackedMethodStrategyManager); diff --git a/main/OpenCover.Framework/Model/Method.cs b/main/OpenCover.Framework/Model/Method.cs index afb790437..5760981a7 100644 --- a/main/OpenCover.Framework/Model/Method.cs +++ b/main/OpenCover.Framework/Model/Method.cs @@ -3,7 +3,7 @@ // // This source code is released under the MIT License; see the accompanying license file. // -using System.Collections.Generic; + using System.Xml.Serialization; namespace OpenCover.Framework.Model @@ -95,6 +95,10 @@ public class Method : SummarySkippedEntity [XmlAttribute("isSetter")] public bool IsSetter { get; set; } + /// + /// Mark an entity as skipped + /// + /// Provide a reason public override void MarkAsSkipped(SkippedMethod reason) { SkippedDueTo = reason; diff --git a/main/OpenCover.Framework/Model/Module.cs b/main/OpenCover.Framework/Model/Module.cs index c6817e602..0a3b2bd6e 100644 --- a/main/OpenCover.Framework/Model/Module.cs +++ b/main/OpenCover.Framework/Model/Module.cs @@ -3,10 +3,8 @@ // // This source code is released under the MIT License; see the accompanying license file. // -using System; + using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Xml.Serialization; namespace OpenCover.Framework.Model @@ -61,6 +59,10 @@ public Module() [XmlAttribute("hash")] public string ModuleHash { get; set; } + /// + /// Mark an entity as skipped + /// + /// Provide a reason public override void MarkAsSkipped(SkippedMethod reason) { SkippedDueTo = reason; diff --git a/main/OpenCover.Framework/Model/SequencePoint.cs b/main/OpenCover.Framework/Model/SequencePoint.cs index db19eb4a0..8a6d7e32f 100644 --- a/main/OpenCover.Framework/Model/SequencePoint.cs +++ b/main/OpenCover.Framework/Model/SequencePoint.cs @@ -38,9 +38,15 @@ public class SequencePoint : InstrumentationPoint, IDocumentReference [XmlAttribute("ec")] public int EndColumn { get; set; } + /// + /// The number of branch exits + /// [XmlAttribute("bec")] public int BranchExitsCount { get; set; } + /// + /// The number of times the branch exists were visited + /// [XmlAttribute("bev")] public int BranchExitsVisit { get; set; } diff --git a/main/OpenCover.Framework/Model/SkippedEntity.cs b/main/OpenCover.Framework/Model/SkippedEntity.cs index ed771710c..c447ea754 100644 --- a/main/OpenCover.Framework/Model/SkippedEntity.cs +++ b/main/OpenCover.Framework/Model/SkippedEntity.cs @@ -7,7 +7,7 @@ namespace OpenCover.Framework.Model /// public abstract class SkippedEntity { - private SkippedMethod? skippedDueTo; + private SkippedMethod? _skippedDueTo; /// /// If this class has been skipped then this value will describe why @@ -15,14 +15,14 @@ public abstract class SkippedEntity [XmlAttribute("skippedDueTo")] public SkippedMethod SkippedDueTo { - get { return skippedDueTo.GetValueOrDefault(); } - set { skippedDueTo = value; } + get { return _skippedDueTo.GetValueOrDefault(); } + set { _skippedDueTo = value; } } /// /// If this class has been skipped then this value will allow the data to be serialized /// - public bool ShouldSerializeSkippedDueTo() { return skippedDueTo.HasValue; } + public bool ShouldSerializeSkippedDueTo() { return _skippedDueTo.HasValue; } /// /// Mark an entity as skipped diff --git a/main/OpenCover.Framework/Model/SummarySkippedEntity.cs b/main/OpenCover.Framework/Model/SummarySkippedEntity.cs index 1c305c7f7..42f2bbccd 100644 --- a/main/OpenCover.Framework/Model/SummarySkippedEntity.cs +++ b/main/OpenCover.Framework/Model/SummarySkippedEntity.cs @@ -6,6 +6,9 @@ namespace OpenCover.Framework.Model /// public abstract class SummarySkippedEntity : SkippedEntity { + /// + /// Initialise + /// protected SummarySkippedEntity() { Summary = new Summary(); diff --git a/main/OpenCover.Framework/Model/TrackedMethod.cs b/main/OpenCover.Framework/Model/TrackedMethod.cs index f73b3f99c..3a742b84f 100644 --- a/main/OpenCover.Framework/Model/TrackedMethod.cs +++ b/main/OpenCover.Framework/Model/TrackedMethod.cs @@ -18,7 +18,9 @@ public class TrackedMethodRef [XmlAttribute("uid")] public UInt32 UniqueId { get; set; } - // visit count + /// + /// The visit count + /// [XmlAttribute("vc")] public int VisitCount { get; set; } diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index d09e25b1b..ad3e0f892 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -12,6 +12,9 @@ namespace OpenCover.Framework.Persistance /// public abstract class BasePersistance : IPersistance { + /// + /// Provides subclasses access to the command line object + /// protected readonly ICommandLine CommandLine; private readonly ILog _logger; private uint _trackedMethodId; diff --git a/main/OpenCover.Framework/Persistance/FilePersistance.cs b/main/OpenCover.Framework/Persistance/FilePersistance.cs index ffc063810..f1c3cb2c8 100644 --- a/main/OpenCover.Framework/Persistance/FilePersistance.cs +++ b/main/OpenCover.Framework/Persistance/FilePersistance.cs @@ -68,6 +68,9 @@ private void LoadCoverageFile() } } + /// + /// we are done and the data needs one last clean up + /// public override void Commit() { _logger.Info("Committing..."); diff --git a/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs b/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs index a5677b87e..a50678ab8 100644 --- a/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs +++ b/main/OpenCover.Framework/Strategy/TrackedMethodStrategyManager.cs @@ -66,6 +66,12 @@ public TrackedMethodStrategyManager() } private int _methodId; + + /// + /// Get the tracked methods for the target assembly + /// + /// + /// public TrackedMethod[] GetTrackedMethods(string assembly) { var methods = _proxy.GetTrackedMethods(assembly); @@ -76,6 +82,10 @@ public TrackedMethod[] GetTrackedMethods(string assembly) return methods; } + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + /// 2 public void Dispose() { _proxy = null; diff --git a/main/OpenCover.Framework/Utility/PerfCounters.cs b/main/OpenCover.Framework/Utility/PerfCounters.cs index e1774b247..a8feb4832 100644 --- a/main/OpenCover.Framework/Utility/PerfCounters.cs +++ b/main/OpenCover.Framework/Utility/PerfCounters.cs @@ -9,15 +9,19 @@ namespace OpenCover.Framework.Utility public class PerfCounters : IPerfCounters { private PerformanceCounter _memoryQueue; - private PerformanceCounter _queueThrougput; + private PerformanceCounter _queueThroughput; /// /// get the current queue size /// public int CurrentMemoryQueueSize { set { _memoryQueue.RawValue = value; } } + + /// + /// Increment the block size + /// public void IncrementBlocksReceived() { - _queueThrougput.RawValue += 1; + _queueThroughput.RawValue += 1; } /// @@ -50,13 +54,16 @@ private void CreateCounters() PerformanceCounterCategoryType.SingleInstance, counters); _memoryQueue = new PerformanceCounter(CategoryName, MemoryQueue, false) { RawValue = 0 }; - _queueThrougput = new PerformanceCounter(CategoryName, QueueThroughput, false) { RawValue = 0 }; + _queueThroughput = new PerformanceCounter(CategoryName, QueueThroughput, false) { RawValue = 0 }; } + /// + /// Reset all counters + /// public void ResetCounters() { _memoryQueue.RawValue = 0; - _queueThrougput.RawValue = 0; + _queueThroughput.RawValue = 0; } } @@ -69,11 +76,19 @@ public class NullPerfCounter : IPerfCounters /// /// A null performance counters implementation /// + // ReSharper disable once UnusedAutoPropertyAccessor.Local public int CurrentMemoryQueueSize { set; private get; } + + /// + /// Increment the number of blocks received + /// public void IncrementBlocksReceived() { } + /// + /// Reset all counters + /// public void ResetCounters() { } From b918e21297763da7923768ea3b3d7899b4e935d2 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Lafay Date: Tue, 10 Nov 2015 13:47:20 +0100 Subject: [PATCH 06/41] Add line feed to traces --- main/OpenCover.Profiler/CodeCoverage.cpp | 40 ++--- .../CodeCoverage_Cuckoo.cpp | 14 +- .../CodeCoverage_ProfilerInfo.cpp | 2 +- .../CodeCoverage_Support.cpp | 24 +-- .../CodeCoverage_Thread.cpp | 8 +- main/OpenCover.Profiler/Method.cpp | 28 ++-- .../ProfilerCommunication.cpp | 56 +++---- main/OpenCover.Profiler/ProfilerInfo.cpp | 2 +- main/OpenCover.Profiler/ProfilerInfoBase.h | 156 +++++++++--------- main/OpenCover.Profiler/Synchronization.h | 4 +- 10 files changed, 167 insertions(+), 167 deletions(-) diff --git a/main/OpenCover.Profiler/CodeCoverage.cpp b/main/OpenCover.Profiler/CodeCoverage.cpp index 0e7cd679f..489eda021 100644 --- a/main/OpenCover.Profiler/CodeCoverage.cpp +++ b/main/OpenCover.Profiler/CodeCoverage.cpp @@ -22,7 +22,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::Initialize( } HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ - ATLTRACE(_T("::OpenCoverInitialise")); + ATLTRACE(_T("::OpenCoverInitialise\n")); OLECHAR szGuid[40]={0}; int nCount = ::StringFromGUID2(CLSID_CodeCoverage, szGuid, 40); @@ -39,13 +39,13 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ //::OutputDebugStringW(szModuleName); if (g_pProfiler!=NULL) - RELTRACE(_T("Another instance of the profiler is running under this process...")); + RELTRACE(_T("Another instance of the profiler is running under this process...\n")); m_profilerInfo = pICorProfilerInfoUnk; - if (m_profilerInfo != NULL) ATLTRACE(_T(" ::Initialize (m_profilerInfo OK)")); + if (m_profilerInfo != NULL) ATLTRACE(_T(" ::Initialize (m_profilerInfo OK)\n")); if (m_profilerInfo == NULL) return E_FAIL; m_profilerInfo2 = pICorProfilerInfoUnk; - if (m_profilerInfo2 != NULL) ATLTRACE(_T(" ::Initialize (m_profilerInfo2 OK)")); + if (m_profilerInfo2 != NULL) ATLTRACE(_T(" ::Initialize (m_profilerInfo2 OK)\n")); if (m_profilerInfo2 == NULL) return E_FAIL; m_profilerInfo3 = pICorProfilerInfoUnk; #ifndef _TOOLSETV71 @@ -55,7 +55,7 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ ZeroMemory(&m_runtimeVersion, sizeof(m_runtimeVersion)); if (m_profilerInfo3 != NULL) { - ATLTRACE(_T(" ::Initialize (m_profilerInfo3 OK)")); + ATLTRACE(_T(" ::Initialize (m_profilerInfo3 OK)\n")); ZeroMemory(&m_runtimeVersion, sizeof(m_runtimeVersion)); m_profilerInfo3->GetRuntimeInformation(NULL, &m_runtimeType, @@ -64,37 +64,37 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ &m_runtimeVersion.usBuildNumber, &m_runtimeVersion.usRevisionNumber, 0, NULL, NULL); - ATLTRACE(_T(" ::Initialize (Runtime %d)"), m_runtimeType); + ATLTRACE(_T(" ::Initialize (Runtime %d)\n"), m_runtimeType); } TCHAR key[1024] = {0}; ::GetEnvironmentVariable(_T("OpenCover_Profiler_Key"), key, 1024); - RELTRACE(_T(" ::Initialize(...) => key = %s"), key); + RELTRACE(_T(" ::Initialize(...) => key = %s\n"), key); TCHAR ns[1024] = {0}; ::GetEnvironmentVariable(_T("OpenCover_Profiler_Namespace"), ns, 1024); - ATLTRACE(_T(" ::Initialize(...) => ns = %s"), ns); + ATLTRACE(_T(" ::Initialize(...) => ns = %s\n"), ns); TCHAR instrumentation[1024] = {0}; ::GetEnvironmentVariable(_T("OpenCover_Profiler_Instrumentation"), instrumentation, 1024); - ATLTRACE(_T(" ::Initialize(...) => instrumentation = %s"), instrumentation); + ATLTRACE(_T(" ::Initialize(...) => instrumentation = %s\n"), instrumentation); TCHAR threshold[1024] = {0}; ::GetEnvironmentVariable(_T("OpenCover_Profiler_Threshold"), threshold, 1024); m_threshold = _tcstoul(threshold, NULL, 10); - ATLTRACE(_T(" ::Initialize(...) => threshold = %ul"), m_threshold); + ATLTRACE(_T(" ::Initialize(...) => threshold = %ul\n"), m_threshold); TCHAR tracebyTest[1024] = {0}; ::GetEnvironmentVariable(_T("OpenCover_Profiler_TraceByTest"), tracebyTest, 1024); m_tracingEnabled = _tcslen(tracebyTest) != 0; - ATLTRACE(_T(" ::Initialize(...) => tracingEnabled = %s (%s)"), m_tracingEnabled ? _T("true") : _T("false"), tracebyTest); + ATLTRACE(_T(" ::Initialize(...) => tracingEnabled = %s (%s)"), m_tracingEnabled ? _T("true") : _T("false\n"), tracebyTest); m_useOldStyle = (tstring(instrumentation) == _T("oldSchool")); if (!m_host.Initialise(key, ns, szExeName)) { - RELTRACE(_T(" ::Initialize => Profiler will not run for this process.")); + RELTRACE(_T(" ::Initialize => Profiler will not run for this process.\n")); return E_FAIL; } @@ -125,7 +125,7 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ _FunctionEnter2, _FunctionLeave2, _FunctionTailcall2), _T(" ::Initialize(...) => SetEnterLeaveFunctionHooks2 => 0x%X")); #endif - RELTRACE(_T("::Initialize - Done!")); + RELTRACE(_T("::Initialize - Done!\n")); return S_OK; } @@ -148,7 +148,7 @@ DWORD CCodeCoverage::AppendProfilerEventMask(DWORD currentEventMask) #ifndef _TOOLSETV71 if (m_profilerInfo4 != NULL) { - ATLTRACE(_T(" ::Initialize (m_profilerInfo4 OK)")); + ATLTRACE(_T(" ::Initialize (m_profilerInfo4 OK)\n")); dwMask |= COR_PRF_DISABLE_ALL_NGEN_IMAGES; } #endif @@ -161,7 +161,7 @@ DWORD CCodeCoverage::AppendProfilerEventMask(DWORD currentEventMask) /// Handle ICorProfilerCallback::Shutdown HRESULT STDMETHODCALLTYPE CCodeCoverage::Shutdown( void) { - RELTRACE(_T("::Shutdown - Starting")); + RELTRACE(_T("::Shutdown - Starting\n")); if (m_chainedProfiler != NULL) m_chainedProfiler->Shutdown(); @@ -170,7 +170,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::Shutdown( void) WCHAR szExeName[MAX_PATH]; GetModuleFileNameW(NULL, szExeName, MAX_PATH); - RELTRACE(_T("::Shutdown - Nothing left to do but return S_OK(%s)"), szExeName); + RELTRACE(_T("::Shutdown - Nothing left to do but return S_OK(%s)\n"), szExeName); g_pProfiler = NULL; return S_OK; } @@ -233,14 +233,14 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ModuleAttachedToAssembly( std::wstring modulePath = GetModulePath(moduleId); std::wstring assemblyName = GetAssemblyName(assemblyId); - /*ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)"), + /*ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)\n"), moduleId, W2CT(modulePath.c_str()), assemblyId, W2CT(assemblyName.c_str()));*/ 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)"), + ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)\n"), moduleId, W2CT(modulePath.c_str()), assemblyId, W2CT(assemblyName.c_str())); } @@ -268,7 +268,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( if (m_allowModules[modulePath]) { - ATLTRACE(_T("::JITCompilationStarted(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(modulePath.c_str())); + ATLTRACE(_T("::JITCompilationStarted(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(modulePath.c_str())); std::vector seqPoints; std::vector brPoints; @@ -288,7 +288,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( Method instumentedMethod(pMethod); instumentedMethod.IncrementStackSize(2); - ATLTRACE(_T("::JITCompilationStarted(...) => Instrumenting...")); + ATLTRACE(_T("::JITCompilationStarted(...) => Instrumenting...\n")); //seqPoints.clear(); //brPoints.clear(); diff --git a/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp b/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp index ab47a0e52..b5a53a7a3 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp @@ -37,7 +37,7 @@ HRESULT CCodeCoverage::RegisterCuckoos(ModuleID moduleId){ mdTypeDef systemObject = mdTokenNil; if (S_OK == metaDataImport->FindTypeDefByName(L"System.Object", mdTokenNil, &systemObject)) { - RELTRACE(_T("::ModuleLoadFinished(...) => Adding methods to mscorlib...")); + RELTRACE(_T("::ModuleLoadFinished(...) => Adding methods to mscorlib...\n")); mdMethodDef systemObjectCtor; COM_FAIL_MSG_RETURN_ERROR(metaDataImport->FindMethod(systemObject, L".ctor", ctorCallSignature, sizeof(ctorCallSignature), &systemObjectCtor), @@ -122,7 +122,7 @@ HRESULT CCodeCoverage::RegisterCuckoos(ModuleID moduleId){ COM_FAIL_MSG_RETURN_ERROR(metaDataEmit->DefineCustomAttribute(m_cuckooSafeToken, attributeCtor, NULL, 0, &customAttr), _T(" ::ModuleLoadFinished(...) => DefineCustomAttribute => 0x%X")); - RELTRACE(_T("::ModuleLoadFinished(...) => Added methods to mscorlib")); + RELTRACE(_T("::ModuleLoadFinished(...) => Added methods to mscorlib\n")); } return S_OK; @@ -130,7 +130,7 @@ HRESULT CCodeCoverage::RegisterCuckoos(ModuleID moduleId){ mdMemberRef CCodeCoverage::RegisterSafeCuckooMethod(ModuleID moduleId) { - ATLTRACE(_T("::RegisterSafeCuckooMethod(%X) => %s"), moduleId, CUCKOO_SAFE_METHOD_NAME); + ATLTRACE(_T("::RegisterSafeCuckooMethod(%X) => %s\n"), moduleId, CUCKOO_SAFE_METHOD_NAME); // for modules we are going to instrument add our reference to the method marked // with the SecuritySafeCriticalAttribute @@ -160,7 +160,7 @@ mdMemberRef CCodeCoverage::RegisterSafeCuckooMethod(ModuleID moduleId) /// This method makes the call into the profiler HRESULT CCodeCoverage::AddCriticalCuckooBody(ModuleID moduleId) { - ATLTRACE(_T("::AddCriticalCuckooBody => Adding VisitedCritical...")); + ATLTRACE(_T("::AddCriticalCuckooBody => Adding VisitedCritical...\n")); mdSignature pvsig = GetMethodSignatureToken_I4(moduleId); void(__fastcall *pt)(ULONG) = GetInstrumentPointVisit(); @@ -181,7 +181,7 @@ HRESULT CCodeCoverage::AddCriticalCuckooBody(ModuleID moduleId) InstrumentMethodWith(moduleId, m_cuckooCriticalToken, instructions); - ATLTRACE(_T("::AddCriticalCuckooBody => Adding VisitedCritical - Done!")); + ATLTRACE(_T("::AddCriticalCuckooBody => Adding VisitedCritical - Done!\n")); return S_OK; } @@ -190,7 +190,7 @@ HRESULT CCodeCoverage::AddCriticalCuckooBody(ModuleID moduleId) /// Calls the method that is marked with the SecurityCriticalAttribute HRESULT CCodeCoverage::AddSafeCuckooBody(ModuleID moduleId) { - ATLTRACE(_T("::AddSafeCuckooBody => Adding SafeVisited...")); + ATLTRACE(_T("::AddSafeCuckooBody => Adding SafeVisited...\n")); BYTE data[] = { (0x01 << 2) | CorILMethod_TinyFormat, CEE_RET }; Method criticalMethod((IMAGE_COR_ILMETHOD*)data); @@ -203,7 +203,7 @@ HRESULT CCodeCoverage::AddSafeCuckooBody(ModuleID moduleId) InstrumentMethodWith(moduleId, m_cuckooSafeToken, instructions); - ATLTRACE(_T("::AddSafeCuckooBody => Adding SafeVisited - Done!")); + ATLTRACE(_T("::AddSafeCuckooBody => Adding SafeVisited - Done!\n")); return S_OK; } diff --git a/main/OpenCover.Profiler/CodeCoverage_ProfilerInfo.cpp b/main/OpenCover.Profiler/CodeCoverage_ProfilerInfo.cpp index aaa996a1d..15a947862 100644 --- a/main/OpenCover.Profiler/CodeCoverage_ProfilerInfo.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_ProfilerInfo.cpp @@ -172,7 +172,7 @@ std::wstring CCodeCoverage::GetTypeAndMethodName(FunctionID functionId) methodName += L"::"; methodName += szMethodName; - //ATLTRACE(_T("::GetTypeAndMethodName(%s)"), W2CT(methodName.c_str())); + //ATLTRACE(_T("::GetTypeAndMethodName(%s)\n"), W2CT(methodName.c_str())); return methodName; } diff --git a/main/OpenCover.Profiler/CodeCoverage_Support.cpp b/main/OpenCover.Profiler/CodeCoverage_Support.cpp index 10abe8cd2..4ef3b9661 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Support.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Support.cpp @@ -62,7 +62,7 @@ LPSAFEARRAY GetInjectedDllAsSafeArray() EXTERN_C HRESULT STDAPICALLTYPE LoadOpenCoverSupportAssembly(IUnknown *pUnk) { - ATLTRACE(_T("****LoadInjectorAssembly - Start****")); + ATLTRACE(_T("****LoadInjectorAssembly - Start****\n")); CComPtr<_AppDomain> pAppDomain; HRESULT hr = pUnk->QueryInterface(__uuidof(_AppDomain), (void**)&pAppDomain); @@ -86,7 +86,7 @@ EXTERN_C HRESULT STDAPICALLTYPE LoadOpenCoverSupportAssembly(IUnknown *pUnk) hr = pDomainHelper->AddResolveEventHandler(); ATLASSERT(hr == S_OK); - ATLTRACE(_T("****LoadInjectorAssembly - End****")); + ATLTRACE(_T("****LoadInjectorAssembly - End****\n")); return S_OK; } @@ -98,13 +98,13 @@ HRESULT CCodeCoverage::OpenCoverSupportInitialize( ::GetEnvironmentVariable(_T("CHAIN_EXTERNAL_PROFILER"), ext, 1024); if (ext[0] != 0) { - ATLTRACE(_T("::OpenCoverSupportInitialize")); + ATLTRACE(_T("::OpenCoverSupportInitialize\n")); - ATLTRACE(_T(" ::Initialize(...) => ext = %s"), ext); + ATLTRACE(_T(" ::Initialize(...) => ext = %s\n"), ext); TCHAR loc[1024] = { 0 }; ::GetEnvironmentVariable(_T("CHAIN_EXTERNAL_PROFILER_LOCATION"), loc, 1024); - ATLTRACE(_T(" ::Initialize(...) => loc = %s"), loc); + ATLTRACE(_T(" ::Initialize(...) => loc = %s\n"), loc); CLSID clsid; HRESULT hr = CLSIDFromString(T2OLE(ext), &clsid); @@ -134,7 +134,7 @@ HRESULT CCodeCoverage::OpenCoverSupportInitialize( hr = m_chainedProfiler->Initialize(m_infoHook); - ATLTRACE(_T(" ::OpenCoverSupportInitialize => fakes = 0x%X"), hr); + ATLTRACE(_T(" ::OpenCoverSupportInitialize => fakes = 0x%X\n"), hr); } return S_OK; @@ -360,7 +360,7 @@ void CCodeCoverage::InstrumentTestToolsUITesting(FunctionID functionId, mdToken if (APPLICATIONUNDERTEST_CCTOR == typeMethodName) { - ATLTRACE(_T("::InstrumentTestToolsUITesting(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + ATLTRACE(_T("::InstrumentTestToolsUITesting(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); mdMethodDef invokeAttach = CreatePInvokeHook(moduleId); InstructionList instructions; @@ -374,7 +374,7 @@ void CCodeCoverage::InstrumentTestToolsUITesting(FunctionID functionId, mdToken if (APPLICATIONUNDERTEST_START == typeMethodName) { - ATLTRACE(_T("::InstrumentTestToolsUITesting(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + ATLTRACE(_T("::InstrumentTestToolsUITesting(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); mdMemberRef memberRef = GetUITestingHelperMethodRef(_T("PropagateRequiredEnvironmentVariables"), moduleId); InstructionList instructions; @@ -395,7 +395,7 @@ void CCodeCoverage::InstrumentTestPlatformUtilities(FunctionID functionId, mdTok if (DEFAULTTESTEXECUTOR_CTOR == typeMethodName) { - ATLTRACE(_T("::InstrumentTestPlatformUtilities(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + ATLTRACE(_T("::InstrumentTestPlatformUtilities(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); mdMethodDef invokeAttach = CreatePInvokeHook(moduleId); InstructionList instructions; @@ -409,7 +409,7 @@ void CCodeCoverage::InstrumentTestPlatformUtilities(FunctionID functionId, mdTok if (DEFAULTTESTEXECUTOR_LAUNCHPROCESS == typeMethodName) { - ATLTRACE(_T("::InstrumentTestPlatformUtilities(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + ATLTRACE(_T("::InstrumentTestPlatformUtilities(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); mdMemberRef memberRef = GetFakesHelperMethodRef(_T("LoadOpenCoverProfilerInstead"), moduleId); InstructionList instructions; @@ -430,7 +430,7 @@ void CCodeCoverage::InstrumentTestPlatformTestExecutor(FunctionID functionId, md if (TESTEXECUTORMAIN_CTOR == typeMethodName) { - ATLTRACE(_T("::InstrumentTestPlatformTestExecutor(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + ATLTRACE(_T("::InstrumentTestPlatformTestExecutor(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); mdMethodDef invokeAttach = CreatePInvokeHook(moduleId); @@ -445,7 +445,7 @@ void CCodeCoverage::InstrumentTestPlatformTestExecutor(FunctionID functionId, md if (TESTEXECUTORMAIN_RUN == typeMethodName) { - ATLTRACE(_T("::InstrumentTestPlatformTestExecutor(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + ATLTRACE(_T("::InstrumentTestPlatformTestExecutor(%X, ...) => %d, %X => %s\n"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); mdMemberRef memberRef = GetFakesHelperMethodRef(_T("PretendWeLoadedFakesProfiler"), moduleId); InstructionList instructions; diff --git a/main/OpenCover.Profiler/CodeCoverage_Thread.cpp b/main/OpenCover.Profiler/CodeCoverage_Thread.cpp index 921af6db6..f3ecd288a 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Thread.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Thread.cpp @@ -7,7 +7,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadCreated( /* [in] */ ThreadID threadId) { - ATLTRACE(_T("::ThreadCreated(%d)"), threadId); + ATLTRACE(_T("::ThreadCreated(%d)\n"), threadId); if (m_chainedProfiler != NULL) m_chainedProfiler->ThreadCreated(threadId); return S_OK; @@ -16,7 +16,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadCreated( HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadDestroyed( /* [in] */ ThreadID threadId) { - ATLTRACE(_T("::ThreadDestroyed(%d)"), threadId); + ATLTRACE(_T("::ThreadDestroyed(%d)\n"), threadId); if (m_chainedProfiler != NULL) m_chainedProfiler->ThreadDestroyed(threadId); @@ -31,7 +31,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadAssignedToOSThread( /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId) { - ATLTRACE(_T("::ThreadAssignedToOSThread(%d, %d)"), managedThreadId, osThreadId); + ATLTRACE(_T("::ThreadAssignedToOSThread(%d, %d)\n"), managedThreadId, osThreadId); if (m_chainedProfiler != NULL) m_chainedProfiler->ThreadAssignedToOSThread(managedThreadId, osThreadId); @@ -48,7 +48,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadNameChanged( /* [in] */ __in_ecount_opt(cchName) WCHAR name[]) { - ATLTRACE(_T("::ThreadNameChanged(%d, %s)"), threadId, W2T(name)); + ATLTRACE(_T("::ThreadNameChanged(%d, %s)\n"), threadId, W2T(name)); if (m_chainedProfiler != NULL) m_chainedProfiler->ThreadNameChanged(threadId, cchName, name); return S_OK; diff --git a/main/OpenCover.Profiler/Method.cpp b/main/OpenCover.Profiler/Method.cpp index da2c6a48c..b6342c246 100644 --- a/main/OpenCover.Profiler/Method.cpp +++ b/main/OpenCover.Profiler/Method.cpp @@ -41,17 +41,17 @@ void Method::ReadMethod(IMAGE_COR_ILMETHOD* pMethod) COR_ILMETHOD_FAT* fatImage = (COR_ILMETHOD_FAT*)&pMethod->Fat; if(!fatImage->IsFat()) { - ATLTRACE(_T("TINY")); + ATLTRACE(_T("TINY\n")); COR_ILMETHOD_TINY* tinyImage = (COR_ILMETHOD_TINY*)&pMethod->Tiny; m_header.CodeSize = tinyImage->GetCodeSize(); pCode = tinyImage->GetCode(); - ATLTRACE(_T("TINY(%X) => (%d + 1) : %d"), m_header.CodeSize, m_header.CodeSize, m_header.MaxStack); + ATLTRACE(_T("TINY(%X) => (%d + 1) : %d\n"), m_header.CodeSize, m_header.CodeSize, m_header.MaxStack); } else { memcpy(&m_header, pMethod, fatImage->Size * sizeof(DWORD)); pCode = fatImage->GetCode(); - ATLTRACE(_T("FAT(%X) => (%d + 12) : %d"), m_header.CodeSize, m_header.CodeSize, m_header.MaxStack); + ATLTRACE(_T("FAT(%X) => (%d + 12) : %d\n"), m_header.CodeSize, m_header.CodeSize, m_header.MaxStack); } SetBuffer(pCode); ReadBody(); @@ -437,25 +437,25 @@ void Method::ResolveBranches() void Method::DumpIL() { #ifdef DUMP_IL - ATLTRACE(_T("-+-+-+-+-+-+-+-+-+-+-+-+- START -+-+-+-+-+-+-+-+-+-+-+-+")); + ATLTRACE(_T("-+-+-+-+-+-+-+-+-+-+-+-+- START -+-+-+-+-+-+-+-+-+-+-+-+\n")); for (auto it = m_instructions.begin(); it != m_instructions.end() ; ++it) { OperationDetails &details = Operations::m_mapNameOperationDetails[(*it)->m_operation]; if (details.operandSize == Null) { - ATLTRACE(_T("IL_%04X %s"), (*it)->m_offset, details.stringName); + ATLTRACE(_T("IL_%04X %s\n"), (*it)->m_offset, details.stringName); } else { if (details.operandParam == ShortInlineBrTarget || details.operandParam == InlineBrTarget) { long offset = (*it)->m_offset + (*it)->m_branchOffsets[0] + details.length + details.operandSize; - ATLTRACE(_T("IL_%04X %s IL_%04X"), + ATLTRACE(_T("IL_%04X %s IL_%04X\n"), (*it)->m_offset, details.stringName, offset); } else if (details.operandParam == InlineMethod || details.operandParam == InlineString) { - ATLTRACE(_T("IL_%04X %s (%02X)%02X%02X%02X"), + ATLTRACE(_T("IL_%04X %s (%02X)%02X%02X%02X\n"), (*it)->m_offset, details.stringName, (BYTE)((*it)->m_operand >> 24), (BYTE)((*it)->m_operand >> 16), @@ -464,22 +464,22 @@ void Method::DumpIL() } else if (details.operandSize == Byte) { - ATLTRACE(_T("IL_%04X %s %02X"), + ATLTRACE(_T("IL_%04X %s %02X\n"), (*it)->m_offset, details.stringName, (*it)->m_operand); } else if (details.operandSize == Word) { - ATLTRACE(_T("IL_%04X %s %04X"), + ATLTRACE(_T("IL_%04X %s %04X\n"), (*it)->m_offset, details.stringName, (*it)->m_operand); } else if (details.operandSize == Dword) { - ATLTRACE(_T("IL_%04X %s %08X"), + ATLTRACE(_T("IL_%04X %s %08X\n"), (*it)->m_offset, details.stringName, (*it)->m_operand); } else { - ATLTRACE(_T("IL_%04X %s %X"), (*it)->m_offset, details.stringName, (*it)->m_operand); + ATLTRACE(_T("IL_%04X %s %X\n"), (*it)->m_offset, details.stringName, (*it)->m_operand); } } for (std::vector::iterator offsetIter = (*it)->m_branchOffsets.begin(); offsetIter != (*it)->m_branchOffsets.end() ; offsetIter++) @@ -487,7 +487,7 @@ void Method::DumpIL() if ((*it)->m_operation == CEE_SWITCH) { long offset = (*it)->m_offset + (4*(long)(*it)->m_operand) + (*offsetIter) + details.length + details.operandSize; - ATLTRACE(_T(" IL_%04X"), offset); + ATLTRACE(_T(" IL_%04X\n"), offset); } } } @@ -495,7 +495,7 @@ void Method::DumpIL() int i = 0; for (auto it = m_exceptions.begin(); it != m_exceptions.end() ; ++it) { - ATLTRACE(_T("Section %d: %d %04X %04X %04X %04X %04X %08X"), + ATLTRACE(_T("Section %d: %d %04X %04X %04X %04X %04X %08X\n"), i++, (*it)->m_handlerType, (*it)->m_tryStart != NULL ? (*it)->m_tryStart->m_offset : 0, (*it)->m_tryEnd != NULL ? (*it)->m_tryEnd->m_offset : 0, @@ -504,7 +504,7 @@ void Method::DumpIL() (*it)->m_filterStart != NULL ? (*it)->m_filterStart->m_offset : 0, (*it)->m_token); } - ATLTRACE(_T("-+-+-+-+-+-+-+-+-+-+-+-+- END -+-+-+-+-+-+-+-+-+-+-+-+")); + ATLTRACE(_T("-+-+-+-+-+-+-+-+-+-+-+-+- END -+-+-+-+-+-+-+-+-+-+-+-+\n")); #endif } diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp index 0e7501ce7..ce49786db 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.cpp +++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp @@ -40,50 +40,50 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName if (!m_mutexCommunication.IsValid()) return false; USES_CONVERSION; - ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised mutexes => %s"), W2CT(sharedKey.c_str())); + ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised mutexes => %s\n"), W2CT(sharedKey.c_str())); auto resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + sharedKey); m_eventProfilerRequestsInformation.Initialise(resource_name.c_str()); if (!m_eventProfilerRequestsInformation.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ChunkData_Event_") + sharedKey); m_eventInformationReadByProfiler.Initialise(resource_name.c_str()); if (!m_eventInformationReadByProfiler.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) = >Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) = >Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ReceiveData_Event_") + sharedKey); m_eventInformationReadyForProfiler.Initialise(resource_name.c_str()); if (!m_eventInformationReadyForProfiler.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_MemoryMapFile_") + sharedKey); m_memoryCommunication.OpenFileMapping(resource_name.c_str()); if (!m_memoryCommunication.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_Semaphore_") + sharedKey); _semapore_communication.Initialise(resource_name.c_str()); if (!_semapore_communication.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } m_pMSG = (MSG_Union*)m_memoryCommunication.MapViewOfFile(0, 0, MAX_MSG_SIZE); hostCommunicationActive = true; - ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised communication interface => %s"), W2CT(sharedKey.c_str())); + ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised communication interface => %s\n"), W2CT(sharedKey.c_str())); if (!TrackProcess()){ - RELTRACE(_T("ProfilerCommunication::Initialise(...) => ProfilerCommunication => process is not be tracked")); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => ProfilerCommunication => process is not be tracked\n")); return false; } @@ -99,12 +99,12 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName memoryKey = m_key + memoryKey; - ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Re-initialising communication interface => %s"), W2CT(memoryKey.c_str())); + ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Re-initialising communication interface => %s\n"), W2CT(memoryKey.c_str())); resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + memoryKey); m_eventProfilerRequestsInformation.Initialise(resource_name.c_str()); if (!m_eventProfilerRequestsInformation.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -112,7 +112,7 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ChunkData_Event_") + memoryKey); m_eventInformationReadByProfiler.Initialise(resource_name.c_str()); if (!m_eventInformationReadByProfiler.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -120,7 +120,7 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ReceiveData_Event_") + memoryKey); m_eventInformationReadyForProfiler.Initialise(resource_name.c_str()); if (!m_eventInformationReadyForProfiler.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -128,7 +128,7 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_MemoryMapFile_") + memoryKey); m_memoryCommunication.OpenFileMapping(resource_name.c_str()); if (!m_memoryCommunication.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -138,17 +138,17 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_Semaphore_") + memoryKey); _semapore_communication.Initialise(resource_name.c_str()); if (!_semapore_communication.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } - ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Re-initialised communication interface => %s"), W2CT(memoryKey.c_str())); + ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Re-initialised communication interface => %s\n"), W2CT(memoryKey.c_str())); resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_SendResults_Event_") + memoryKey); m_eventProfilerHasResults.Initialise(resource_name.c_str()); if (!m_eventProfilerHasResults.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -156,7 +156,7 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_ReceiveResults_Event_") + memoryKey); m_eventResultsHaveBeenReceived.Initialise(resource_name.c_str()); if (!m_eventResultsHaveBeenReceived.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -164,7 +164,7 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_MemoryMapFile_") + memoryKey); m_memoryResults.OpenFileMapping(resource_name.c_str()); if (!m_memoryResults.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } @@ -176,12 +176,12 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_Semaphore_") + memoryKey); _semapore_results.Initialise(resource_name.c_str()); if (!_semapore_results.IsValid()) { - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d\n"), W2CT(resource_name.c_str()), ::GetLastError()); hostCommunicationActive = false; return false; } - RELTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised results interface => %s"), W2CT(memoryKey.c_str())); + RELTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised results interface => %s\n"), W2CT(memoryKey.c_str())); } else { hostCommunicationActive = false; @@ -302,7 +302,7 @@ void ProfilerCommunication::SendVisitPoints() if (WAIT_OBJECT_0 != dwSignal) throw CommunicationException(dwSignal, COMM_WAIT_SHORT); m_eventResultsHaveBeenReceived.Reset(); } catch (CommunicationException ex) { - RELTRACE(_T("ProfilerCommunication::SendVisitPoints() => Communication (Results channel) with host has failed (0x%x, %d)"), + RELTRACE(_T("ProfilerCommunication::SendVisitPoints() => Communication (Results channel) with host has failed (0x%x, %d)\n"), ex.getReason(), ex.getTimeout()); hostCommunicationActive = false; } @@ -342,7 +342,7 @@ bool ProfilerCommunication::GetSequencePoints(mdToken functionToken, WCHAR* pMod [=, &points]()->BOOL { if (m_pMSG->getSequencePointsResponse.count > SEQ_BUFFER_SIZE){ - RELTRACE(_T("Received an abnormal count for sequence points (%d) for token 0x%X"), + RELTRACE(_T("Received an abnormal count for sequence points (%d) for token 0x%X\n"), m_pMSG->getSequencePointsResponse.count, functionToken); points.clear(); return false; @@ -379,7 +379,7 @@ bool ProfilerCommunication::GetBranchPoints(mdToken functionToken, WCHAR* pModul [=, &points]()->BOOL { if (m_pMSG->getBranchPointsResponse.count > BRANCH_BUFFER_SIZE){ - RELTRACE(_T("Received an abnormal count for branch points (%d) for token 0x%X"), + RELTRACE(_T("Received an abnormal count for branch points (%d) for token 0x%X\n"), m_pMSG->getBranchPointsResponse.count, functionToken); points.clear(); return false; @@ -547,12 +547,12 @@ bool ProfilerCommunication::TrackProcess(){ void ProfilerCommunication::report_runtime(const std::runtime_error& re, const tstring &msg){ USES_CONVERSION; - RELTRACE(_T("Runtime error: %s - %s"), msg.c_str(), A2T(re.what())); + RELTRACE(_T("Runtime error: %s - %s\n"), msg.c_str(), A2T(re.what())); } void ProfilerCommunication::report_exception(const std::exception& re, const tstring &msg){ USES_CONVERSION; - RELTRACE(_T("Error occurred: %s - %s"), msg.c_str(), A2T(re.what())); + RELTRACE(_T("Error occurred: %s - %s\n"), msg.c_str(), A2T(re.what())); } template @@ -562,7 +562,7 @@ void ProfilerCommunication::handle_sehexception(Action action, const tstring& me } __except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { - RELTRACE(_T("SEH exception failure occured: %s - %d"), + RELTRACE(_T("SEH exception failure occured: %s - %d\n"), message.c_str(), GetExceptionCode()); } } @@ -591,7 +591,7 @@ void ProfilerCommunication::handle_exception(Action action, const tstring& messa catch (...) { // catch any other errors (that we have no information about) - RELTRACE(_T("Unknown failure occured. Possible memory corruption - %s"), message.c_str()); + RELTRACE(_T("Unknown failure occured. Possible memory corruption - %s\n"), message.c_str()); throw; } } @@ -633,7 +633,7 @@ void ProfilerCommunication::RequestInformation(BR buildRequest, PR processResult m_eventInformationReadByProfiler.Set(); } catch (CommunicationException ex) { - RELTRACE(_T("ProfilerCommunication::RequestInformation(...) => Communication (Chat channel - %s) with host has failed (0x%x, %d)"), + RELTRACE(_T("ProfilerCommunication::RequestInformation(...) => Communication (Chat channel - %s) with host has failed (0x%x, %d)\n"), message.c_str(), ex.getReason(), ex.getTimeout()); hostCommunicationActive = false; } diff --git a/main/OpenCover.Profiler/ProfilerInfo.cpp b/main/OpenCover.Profiler/ProfilerInfo.cpp index d879e259f..a57189d6a 100644 --- a/main/OpenCover.Profiler/ProfilerInfo.cpp +++ b/main/OpenCover.Profiler/ProfilerInfo.cpp @@ -18,7 +18,7 @@ HRESULT STDMETHODCALLTYPE CProfilerInfo::SetEventMask( expected |= COR_PRF_MONITOR_MODULE_LOADS; expected |= COR_PRF_ENABLE_REJIT; // VS2012 only - ATLTRACE(_T("CProfilerInfo::SetEventMask => received => 0x%X, expected 0x%X"), dwEvents, expected); + ATLTRACE(_T("CProfilerInfo::SetEventMask => received => 0x%X, expected 0x%X\n"), dwEvents, expected); ATLASSERT(expected == (dwEvents | expected)); // assert that nothing new has been added that we haven't already tested against if (m_pProfilerHook!=NULL) diff --git a/main/OpenCover.Profiler/ProfilerInfoBase.h b/main/OpenCover.Profiler/ProfilerInfoBase.h index 59465c7ee..9bd79af35 100644 --- a/main/OpenCover.Profiler/ProfilerInfoBase.h +++ b/main/OpenCover.Profiler/ProfilerInfoBase.h @@ -25,7 +25,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE GetClassFromObject( /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId){ - //ATLTRACE(_T("GetClassFromObject")); + //ATLTRACE(_T("GetClassFromObject\n")); return m_pProfilerInfo->GetClassFromObject(objectId, pClassId); } @@ -33,7 +33,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId){ - //ATLTRACE(_T("GetClassFromToken")); + //ATLTRACE(_T("GetClassFromToken\n")); return m_pProfilerInfo->GetClassFromToken(moduleId, typeDef, pClassId); } @@ -41,20 +41,20 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize){ - //ATLTRACE(_T("GetCodeInfo")); + //ATLTRACE(_T("GetCodeInfo\n")); return m_pProfilerInfo->GetCodeInfo(functionId, pStart, pcSize); } virtual HRESULT STDMETHODCALLTYPE GetEventMask( /* [out] */ DWORD *pdwEvents){ - //ATLTRACE(_T("GetEventMask")); + //ATLTRACE(_T("GetEventMask\n")); return m_pProfilerInfo->GetEventMask(pdwEvents); } virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP( /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId){ - //ATLTRACE(_T("GetFunctionFromIP")); + //ATLTRACE(_T("GetFunctionFromIP\n")); return m_pProfilerInfo->GetFunctionFromIP(ip, pFunctionId); } @@ -62,21 +62,21 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId){ - //ATLTRACE(_T("GetFunctionFromToken")); + //ATLTRACE(_T("GetFunctionFromToken\n")); return m_pProfilerInfo->GetFunctionFromToken(moduleId, token, pFunctionId); } virtual HRESULT STDMETHODCALLTYPE GetHandleFromThread( /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread){ - //ATLTRACE(_T("GetHandleFromThread")); + //ATLTRACE(_T("GetHandleFromThread\n")); return m_pProfilerInfo->GetHandleFromThread(threadId, phThread); } virtual HRESULT STDMETHODCALLTYPE GetObjectSize( /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize){ - //ATLTRACE(_T("GetObjectSize")); + //ATLTRACE(_T("GetObjectSize\n")); return m_pProfilerInfo->GetObjectSize(objectId, pcSize); } @@ -85,20 +85,20 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank){ - //ATLTRACE(_T("IsArrayClass")); + //ATLTRACE(_T("IsArrayClass\n")); return m_pProfilerInfo->IsArrayClass(classId, pBaseElemType, pBaseClassId, pcRank); } virtual HRESULT STDMETHODCALLTYPE GetThreadInfo( /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId){ - //ATLTRACE(_T("GetThreadInfo")); + //ATLTRACE(_T("GetThreadInfo\n")); return m_pProfilerInfo->GetThreadInfo(threadId, pdwWin32ThreadId); } virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( /* [out] */ ThreadID *pThreadId){ - //ATLTRACE(_T("GetCurrentThreadID")); + //ATLTRACE(_T("GetCurrentThreadID\n")); return m_pProfilerInfo->GetCurrentThreadID(pThreadId); } @@ -106,7 +106,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken){ - //ATLTRACE(_T("GetClassIDInfo")); + //ATLTRACE(_T("GetClassIDInfo\n")); return m_pProfilerInfo->GetClassIDInfo(classId, pModuleId, pTypeDefToken); } @@ -115,13 +115,13 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken){ - //ATLTRACE(_T("GetFunctionInfo")); + //ATLTRACE(_T("GetFunctionInfo\n")); return m_pProfilerInfo->GetFunctionInfo(functionId, pClassId, pModuleId, pToken); } virtual HRESULT STDMETHODCALLTYPE SetEventMask( /* [in] */ DWORD dwEvents){ - ATLTRACE(_T("CProfilerInfoBase::SetEventMask(0x%X)"), dwEvents); + ATLTRACE(_T("CProfilerInfoBase::SetEventMask(0x%X)\n"), dwEvents); return m_pProfilerInfo->SetEventMask(dwEvents); } @@ -129,13 +129,13 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall){ - //ATLTRACE(_T("SetEnterLeaveFunctionHooks")); + //ATLTRACE(_T("SetEnterLeaveFunctionHooks\n")); return m_pProfilerInfo->SetEnterLeaveFunctionHooks(pFuncEnter, pFuncLeave, pFuncTailcall); } virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper( /* [in] */ FunctionIDMapper *pFunc){ - //ATLTRACE(_T("SetFunctionIDMapper")); + //ATLTRACE(_T("SetFunctionIDMapper\n")); return m_pProfilerInfo->SetFunctionIDMapper(pFunc); } @@ -144,7 +144,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken){ - //ATLTRACE(_T("GetTokenAndMetaDataFromFunction")); + //ATLTRACE(_T("GetTokenAndMetaDataFromFunction\n")); return m_pProfilerInfo->GetTokenAndMetaDataFromFunction(functionId, riid, ppImport, pToken); } @@ -156,7 +156,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[], /* [out] */ AssemblyID *pAssemblyId){ - //ATLTRACE(_T("GetModuleInfo")); + //ATLTRACE(_T("GetModuleInfo\n")); return m_pProfilerInfo->GetModuleInfo(moduleId, ppBaseLoadAddress, cchName, pcchName, szName, pAssemblyId); } @@ -165,7 +165,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut){ - //ATLTRACE(_T("GetModuleMetaData")); + //ATLTRACE(_T("GetModuleMetaData\n")); return m_pProfilerInfo->GetModuleMetaData(moduleId, dwOpenFlags, riid, ppOut); } @@ -174,14 +174,14 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize){ - //ATLTRACE(_T("GetILFunctionBody")); + //ATLTRACE(_T("GetILFunctionBody\n")); return m_pProfilerInfo->GetILFunctionBody(moduleId, methodId, ppMethodHeader, pcbMethodSize); } virtual HRESULT STDMETHODCALLTYPE GetILFunctionBodyAllocator( /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc){ - //ATLTRACE(_T("GetILFunctionBodyAllocator")); + //ATLTRACE(_T("GetILFunctionBodyAllocator\n")); return m_pProfilerInfo->GetILFunctionBodyAllocator(moduleId, ppMalloc); } @@ -189,7 +189,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader){ - //ATLTRACE(_T("SetILFunctionBody")); + //ATLTRACE(_T("SetILFunctionBody\n")); return m_pProfilerInfo->SetILFunctionBody(moduleId, methodid, pbNewILMethodHeader); } @@ -200,7 +200,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[], /* [out] */ ProcessID *pProcessId){ - //ATLTRACE(_T("GetAppDomainInfo")); + //ATLTRACE(_T("GetAppDomainInfo\n")); return m_pProfilerInfo->GetAppDomainInfo(appDomainId, cchName, pcchName, szName, pProcessId); } @@ -212,18 +212,18 @@ class CProfilerInfoBase : public ICorProfilerInfo4 _Out_writes_to_(cchName, *pcchName) WCHAR szName[], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId){ - //ATLTRACE(_T("GetAssemblyInfo")); + //ATLTRACE(_T("GetAssemblyInfo\n")); return m_pProfilerInfo->GetAssemblyInfo(assemblyId, cchName, pcchName, szName, pAppDomainId, pModuleId); } virtual HRESULT STDMETHODCALLTYPE SetFunctionReJIT( /* [in] */ FunctionID functionId){ - //ATLTRACE(_T("SetFunctionReJIT")); + //ATLTRACE(_T("SetFunctionReJIT\n")); return m_pProfilerInfo->SetFunctionReJIT(functionId); } virtual HRESULT STDMETHODCALLTYPE ForceGC(void){ - //ATLTRACE(_T("GetClassFromObject")); + //ATLTRACE(_T("GetClassFromObject\n")); return m_pProfilerInfo->ForceGC(); } @@ -232,39 +232,39 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[]){ - //ATLTRACE(_T("SetILInstrumentedCodeMap")); + //ATLTRACE(_T("SetILInstrumentedCodeMap\n")); return m_pProfilerInfo->SetILInstrumentedCodeMap(functionId, fStartJit, cILMapEntries, rgILMapEntries); } virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionInterface( /* [out] */ IUnknown **ppicd){ - //ATLTRACE(_T("GetInprocInspectionInterface")); + //ATLTRACE(_T("GetInprocInspectionInterface\n")); return m_pProfilerInfo->GetInprocInspectionInterface(ppicd); } virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionIThisThread( /* [out] */ IUnknown **ppicd){ - //ATLTRACE(_T("GetInprocInspectionIThisThread")); + //ATLTRACE(_T("GetInprocInspectionIThisThread\n")); return m_pProfilerInfo->GetInprocInspectionIThisThread(ppicd); } virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId){ - //ATLTRACE(_T("GetThreadContext")); + //ATLTRACE(_T("GetThreadContext\n")); return m_pProfilerInfo->GetThreadContext(threadId, pContextId); } virtual HRESULT STDMETHODCALLTYPE BeginInprocDebugging( /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext){ - //ATLTRACE(_T("BeginInprocDebugging")); + //ATLTRACE(_T("BeginInprocDebugging\n")); return m_pProfilerInfo->BeginInprocDebugging(fThisThreadOnly, pdwProfilerContext); } virtual HRESULT STDMETHODCALLTYPE EndInprocDebugging( /* [in] */ DWORD dwProfilerContext){ - //ATLTRACE(_T("EndInprocDebugging")); + //ATLTRACE(_T("EndInprocDebugging\n")); return m_pProfilerInfo->EndInprocDebugging(dwProfilerContext); } @@ -273,7 +273,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[]){ - //ATLTRACE(_T("GetILToNativeMapping")); + //ATLTRACE(_T("GetILToNativeMapping\n")); return m_pProfilerInfo->GetILToNativeMapping(functionId, cMap, pcMap, map); } @@ -285,7 +285,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[], /* [in] */ ULONG32 contextSize){ - //ATLTRACE(_T("DoStackSnapshot")); + //ATLTRACE(_T("DoStackSnapshot\n")); return m_pProfilerInfo2->DoStackSnapshot(thread, callback, infoFlags, clientData, context, contextSize); } @@ -293,7 +293,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall){ - //ATLTRACE(_T("SetEnterLeaveFunctionHooks2")); + //ATLTRACE(_T("SetEnterLeaveFunctionHooks2\n")); return m_pProfilerInfo2->SetEnterLeaveFunctionHooks2(pFuncEnter, pFuncLeave, pFuncTailcall); } @@ -306,7 +306,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[]){ - //ATLTRACE(_T("GetFunctionInfo2")); + //ATLTRACE(_T("GetFunctionInfo2\n")); return m_pProfilerInfo2->GetFunctionInfo2(funcId, frameInfo, pClassId, pModuleId, pToken, cTypeArgs, pcTypeArgs, typeArgs); } @@ -314,7 +314,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset){ - //ATLTRACE(_T("GetStringLayout")); + //ATLTRACE(_T("GetStringLayout\n")); return m_pProfilerInfo2->GetStringLayout(pBufferLengthOffset, pStringLengthOffset, pBufferOffset); } @@ -324,7 +324,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize){ - //ATLTRACE(_T("GetClassLayout")); + //ATLTRACE(_T("GetClassLayout\n")); return m_pProfilerInfo2->GetClassLayout(classID, rFieldOffset, cFieldOffset, pcFieldOffset, pulClassSize); } @@ -336,7 +336,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[]){ - //ATLTRACE(_T("GetClassIDInfo2")); + //ATLTRACE(_T("GetClassIDInfo2\n")); return m_pProfilerInfo2->GetClassIDInfo2(classId, pModuleId, pTypeDefToken, pParentClassId, cNumTypeArgs, pcNumTypeArgs, typeArgs); } @@ -345,7 +345,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[]){ - //ATLTRACE(_T("GetCodeInfo2")); + //ATLTRACE(_T("GetCodeInfo2\n")); return m_pProfilerInfo2->GetCodeInfo2(functionID, cCodeInfos, pcCodeInfos, codeInfos); } @@ -355,7 +355,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[], /* [out] */ ClassID *pClassID){ - //ATLTRACE(_T("GetClassFromTokenAndTypeArgs")); + //ATLTRACE(_T("GetClassFromTokenAndTypeArgs\n")); return m_pProfilerInfo2->GetClassFromTokenAndTypeArgs(moduleID, typeDef, cTypeArgs, typeArgs, pClassID); } @@ -366,14 +366,14 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[], /* [out] */ FunctionID *pFunctionID){ - //ATLTRACE(_T("GetFunctionFromTokenAndTypeArgs")); + //ATLTRACE(_T("GetFunctionFromTokenAndTypeArgs\n")); return m_pProfilerInfo2->GetFunctionFromTokenAndTypeArgs(moduleID, funcDef, classId, cTypeArgs, typeArgs, pFunctionID); } virtual HRESULT STDMETHODCALLTYPE EnumModuleFrozenObjects( /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum){ - //ATLTRACE(_T("GetClassFromObject")); + //ATLTRACE(_T("GetClassFromObject\n")); return m_pProfilerInfo2->EnumModuleFrozenObjects(moduleID, ppEnum); } @@ -383,21 +383,21 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [size_is][out] */ ULONG32 pDimensionSizes[], /* [size_is][out] */ int pDimensionLowerBounds[], /* [out] */ BYTE **ppData){ - //ATLTRACE(_T("GetArrayObjectInfo")); + //ATLTRACE(_T("GetArrayObjectInfo\n")); return m_pProfilerInfo2->GetArrayObjectInfo(objectId, cDimensions, pDimensionSizes, pDimensionLowerBounds, ppData); } virtual HRESULT STDMETHODCALLTYPE GetBoxClassLayout( /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset){ - //ATLTRACE(_T("GetBoxClassLayout")); + //ATLTRACE(_T("GetBoxClassLayout\n")); return m_pProfilerInfo2->GetBoxClassLayout(classId, pBufferOffset); } virtual HRESULT STDMETHODCALLTYPE GetThreadAppDomain( /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId){ - //ATLTRACE(_T("GetThreadAppDomain")); + //ATLTRACE(_T("GetThreadAppDomain\n")); return m_pProfilerInfo2->GetThreadAppDomain(threadId, pAppDomainId); } @@ -405,7 +405,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress){ - //ATLTRACE(_T("GetRVAStaticAddress")); + //ATLTRACE(_T("GetRVAStaticAddress\n")); return m_pProfilerInfo2->GetRVAStaticAddress(classId, fieldToken, ppAddress); } @@ -414,7 +414,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress){ - //ATLTRACE(_T("GetAppDomainStaticAddress")); + //ATLTRACE(_T("GetAppDomainStaticAddress\n")); return m_pProfilerInfo2->GetAppDomainStaticAddress(classId, fieldToken, appDomainId, ppAddress); } @@ -423,7 +423,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress){ - //ATLTRACE(_T("GetThreadStaticAddress")); + //ATLTRACE(_T("GetThreadStaticAddress\n")); return m_pProfilerInfo2->GetThreadStaticAddress(classId, fieldToken, threadId, ppAddress); } @@ -432,7 +432,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress){ - //ATLTRACE(_T("GetContextStaticAddress")); + //ATLTRACE(_T("GetContextStaticAddress\n")); return m_pProfilerInfo2->GetContextStaticAddress(classId, fieldToken, contextId, ppAddress); } @@ -440,7 +440,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo){ - //ATLTRACE(_T("GetStaticFieldInfo")); + //ATLTRACE(_T("GetStaticFieldInfo\n")); return m_pProfilerInfo2->GetStaticFieldInfo(classId, fieldToken, pFieldInfo); } @@ -448,47 +448,47 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[]){ - //ATLTRACE(_T("GetGenerationBounds")); + //ATLTRACE(_T("GetGenerationBounds\n")); return m_pProfilerInfo2->GetGenerationBounds(cObjectRanges, pcObjectRanges, ranges); } virtual HRESULT STDMETHODCALLTYPE GetObjectGeneration( /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range){ - //ATLTRACE(_T("GetObjectGeneration")); + //ATLTRACE(_T("GetObjectGeneration\n")); return m_pProfilerInfo2->GetObjectGeneration(objectId, range); } virtual HRESULT STDMETHODCALLTYPE GetNotifiedExceptionClauseInfo( /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo){ - //ATLTRACE(_T("GetNotifiedExceptionClauseInfo")); + //ATLTRACE(_T("GetNotifiedExceptionClauseInfo\n")); return m_pProfilerInfo2->GetNotifiedExceptionClauseInfo(pinfo); } public: // ICorProfilerInfo3 virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions( /* [out] */ ICorProfilerFunctionEnum **ppEnum){ - //ATLTRACE(_T("EnumJITedFunctions")); + //ATLTRACE(_T("EnumJITedFunctions\n")); return m_pProfilerInfo3->EnumJITedFunctions(ppEnum); } virtual HRESULT STDMETHODCALLTYPE RequestProfilerDetach( /* [in] */ DWORD dwExpectedCompletionMilliseconds){ - //ATLTRACE(_T("RequestProfilerDetach")); + //ATLTRACE(_T("RequestProfilerDetach\n")); return m_pProfilerInfo3->RequestProfilerDetach(dwExpectedCompletionMilliseconds); } virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper2( /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData){ - //ATLTRACE(_T("SetFunctionIDMapper2")); + //ATLTRACE(_T("SetFunctionIDMapper2\n")); return m_pProfilerInfo3->SetFunctionIDMapper2(pFunc, clientData); } virtual HRESULT STDMETHODCALLTYPE GetStringLayout2( /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset){ - //ATLTRACE(_T("GetStringLayout2")); + //ATLTRACE(_T("GetStringLayout2\n")); return m_pProfilerInfo3->GetStringLayout2(pStringLengthOffset, pBufferOffset); } @@ -496,7 +496,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3){ - //ATLTRACE(_T("SetEnterLeaveFunctionHooks3")); + //ATLTRACE(_T("SetEnterLeaveFunctionHooks3\n")); return m_pProfilerInfo3->SetEnterLeaveFunctionHooks3(pFuncEnter3, pFuncLeave3, pFuncTailcall3); } @@ -504,7 +504,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo){ - //ATLTRACE(_T("SetEnterLeaveFunctionHooks3WithInfo")); + //ATLTRACE(_T("SetEnterLeaveFunctionHooks3WithInfo\n")); return m_pProfilerInfo3->SetEnterLeaveFunctionHooks3WithInfo(pFuncEnter3WithInfo, pFuncLeave3WithInfo, pFuncTailcall3WithInfo); } @@ -514,7 +514,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo){ - //ATLTRACE(_T("GetFunctionEnter3Info")); + //ATLTRACE(_T("GetFunctionEnter3Info\n")); return m_pProfilerInfo3->GetFunctionEnter3Info(functionId, eltInfo, pFrameInfo, pcbArgumentInfo, pArgumentInfo); } @@ -523,7 +523,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange){ - //ATLTRACE(_T("GetFunctionLeave3Info")); + //ATLTRACE(_T("GetFunctionLeave3Info\n")); return m_pProfilerInfo3->GetFunctionLeave3Info(functionId, eltInfo, pFrameInfo, pRetvalRange); } @@ -531,13 +531,13 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo){ - //ATLTRACE(_T("GetFunctionTailcall3Info")); + //ATLTRACE(_T("GetFunctionTailcall3Info\n")); return m_pProfilerInfo3->GetFunctionTailcall3Info(functionId, eltInfo, pFrameInfo); } virtual HRESULT STDMETHODCALLTYPE EnumModules( /* [out] */ ICorProfilerModuleEnum **ppEnum){ - //ATLTRACE(_T("EnumModules")); + //ATLTRACE(_T("EnumModules\n")); return m_pProfilerInfo3->EnumModules(ppEnum); } @@ -552,7 +552,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[]){ - //ATLTRACE(_T("GetRuntimeInformation")); + //ATLTRACE(_T("GetRuntimeInformation\n")); return m_pProfilerInfo3->GetRuntimeInformation(pClrInstanceId, pRuntimeType, pMajorVersion, pMinorVersion, pBuildNumber, pQFEVersion, cchVersionString, pcchVersionString, szVersionString); } @@ -563,7 +563,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress){ - //ATLTRACE(_T("GetThreadStaticAddress2")); + //ATLTRACE(_T("GetThreadStaticAddress2\n")); return m_pProfilerInfo3->GetThreadStaticAddress2(classId, fieldToken, appDomainId, threadId, ppAddress); } @@ -573,7 +573,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[]){ - //ATLTRACE(_T("GetAppDomainsContainingModule")); + //ATLTRACE(_T("GetAppDomainsContainingModule\n")); return m_pProfilerInfo3->GetAppDomainsContainingModule(moduleId, cAppDomainIds, pcAppDomainIds, appDomainIds); } @@ -587,7 +587,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 _Out_writes_to_(cchName, *pcchName) WCHAR szName[], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags){ - //ATLTRACE(_T("GetModuleInfo2")); + //ATLTRACE(_T("GetModuleInfo2\n")); return m_pProfilerInfo3->GetModuleInfo2(moduleId, ppBaseLoadAddress, cchName, pcchName, szName, pAssemblyId, pdwModuleFlags); } @@ -595,12 +595,12 @@ class CProfilerInfoBase : public ICorProfilerInfo4 public: // ICorProfilerInfo4 virtual HRESULT STDMETHODCALLTYPE EnumThreads( /* [out] */ ICorProfilerThreadEnum **ppEnum){ - //ATLTRACE(_T("EnumThreads")); + //ATLTRACE(_T("EnumThreads\n")); return m_pProfilerInfo4->EnumThreads(ppEnum); } virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread(void){ - //ATLTRACE(_T("InitializeCurrentThread")); + //ATLTRACE(_T("InitializeCurrentThread\n")); return m_pProfilerInfo4->InitializeCurrentThread(); } @@ -608,7 +608,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[], /* [size_is][in] */ mdMethodDef methodIds[]){ - //ATLTRACE(_T("RequestReJIT")); + //ATLTRACE(_T("RequestReJIT\n")); return m_pProfilerInfo4->RequestReJIT(cFunctions, moduleIds, methodIds); } @@ -617,7 +617,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [size_is][in] */ ModuleID moduleIds[], /* [size_is][in] */ mdMethodDef methodIds[], /* [size_is][out] */ HRESULT status[]){ - //ATLTRACE(_T("RequestRevert")); + //ATLTRACE(_T("RequestRevert\n")); return m_pProfilerInfo4->RequestRevert(cFunctions, moduleIds, methodIds, status); } @@ -627,7 +627,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[]){ - //ATLTRACE(_T("GetCodeInfo3")); + //ATLTRACE(_T("GetCodeInfo3\n")); return m_pProfilerInfo4->GetCodeInfo3(functionID, reJitId, cCodeInfos, pcCodeInfos, codeInfos); } @@ -635,7 +635,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId){ - //ATLTRACE(_T("GetFunctionFromIP2")); + //ATLTRACE(_T("GetFunctionFromIP2\n")); return m_pProfilerInfo4->GetFunctionFromIP2(ip, pFunctionId, pReJitId); } @@ -644,7 +644,7 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[]){ - //ATLTRACE(_T("GetClassFromObject")); + //ATLTRACE(_T("GetClassFromObject\n")); return m_pProfilerInfo4->GetReJITIDs(functionId, cReJitIds, pcReJitIds, reJitIds); } @@ -654,20 +654,20 @@ class CProfilerInfoBase : public ICorProfilerInfo4 /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[]){ - //ATLTRACE(_T("GetILToNativeMapping2")); + //ATLTRACE(_T("GetILToNativeMapping2\n")); return m_pProfilerInfo4->GetILToNativeMapping2(functionId, reJitId, cMap, pcMap, map); } virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions2( /* [out] */ ICorProfilerFunctionEnum **ppEnum){ - //ATLTRACE(_T("EnumJITedFunctions2")); + //ATLTRACE(_T("EnumJITedFunctions2\n")); return m_pProfilerInfo4->EnumJITedFunctions2(ppEnum); } virtual HRESULT STDMETHODCALLTYPE GetObjectSize2( /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize){ - //ATLTRACE(_T("GetObjectSize2")); + //ATLTRACE(_T("GetObjectSize2\n")); return m_pProfilerInfo4->GetObjectSize2(objectId, pcSize); } diff --git a/main/OpenCover.Profiler/Synchronization.h b/main/OpenCover.Profiler/Synchronization.h index c2022712c..e9cde6d81 100644 --- a/main/OpenCover.Profiler/Synchronization.h +++ b/main/OpenCover.Profiler/Synchronization.h @@ -51,12 +51,12 @@ class CSemaphoreEx : public CSemaphore { LONG prevCount = -1; if (::ReleaseSemaphore(m_hSemaphore, 1, &prevCount) && prevCount == 0){ // +1 if (::WaitForSingleObject(m_hSemaphore, 1000) == WAIT_TIMEOUT){ // -1 - RELTRACE(_T("Semaphore wait timed out => %s"), _handleName.c_str()); + RELTRACE(_T("Semaphore wait timed out => %s\n"), _handleName.c_str()); return -1; } } else { - RELTRACE(_T("Semaphore count failed => %s, %d"), _handleName.c_str(), prevCount); + RELTRACE(_T("Semaphore count failed => %s, %d\n"), _handleName.c_str(), prevCount); } return prevCount; } From f6e03301518a2c656dd9de2d64c599a17d5176bb Mon Sep 17 00:00:00 2001 From: Jean-Jacques Lafay Date: Tue, 10 Nov 2015 18:37:48 +0100 Subject: [PATCH 07/41] Fix incorrect concurrent use of collections + InstrumentationPoint.cs : concurrent calls to InstrumentationPoint's constructor could result in a mismatch between its index in InstrumentationPoints and its UniqueSequencePoint. Moreover, if things can go really bad if the InstrumentationPoints.Add() triggers a resize. + ProfilerCommunication.cpp : the *read* of m_visitmap must also be synchronized, since it is in an "unreadable" state while written to. --- .../Model/InstrumentationPoint.cs | 12 ++++++++---- main/OpenCover.Profiler/ProfilerCommunication.cpp | 12 ++---------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/main/OpenCover.Framework/Model/InstrumentationPoint.cs b/main/OpenCover.Framework/Model/InstrumentationPoint.cs index fbfe6a742..68266f38f 100644 --- a/main/OpenCover.Framework/Model/InstrumentationPoint.cs +++ b/main/OpenCover.Framework/Model/InstrumentationPoint.cs @@ -13,6 +13,7 @@ namespace OpenCover.Framework.Model public class InstrumentationPoint { private static int _instrumentPoint; + private static object _addInstrumentPointSync = new object(); private static readonly List InstrumentPoints; static InstrumentationPoint() @@ -114,10 +115,13 @@ public static bool AddVisitCount(uint spid, uint trackedMethodId, int sum = 1) /// public InstrumentationPoint() { - UniqueSequencePoint = (uint)Interlocked.Increment(ref _instrumentPoint); - InstrumentPoints.Add(this); - OrigSequencePoint = UniqueSequencePoint; - } + lock (_addInstrumentPointSync) + { + UniqueSequencePoint = (uint)++_instrumentPoint; + InstrumentPoints.Add(this); + OrigSequencePoint = UniqueSequencePoint; + } + } /// /// Store the number of visits diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp index ce49786db..5d6b4a41a 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.cpp +++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp @@ -205,16 +205,8 @@ MSG_SendVisitPoints_Request* ProfilerCommunication::AllocateVisitMap(DWORD osThr } MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG osThreadID){ - MSG_SendVisitPoints_Request * p = NULL; - try { - p = m_visitmap[osThreadID]; - if (p == NULL) - p = AllocateVisitMap(osThreadID); - } - catch (...){ - p = AllocateVisitMap(osThreadID); - } - return p; + ATL::CComCritSecLock lock(m_critThreads); + return m_visitmap[osThreadID]; } void ProfilerCommunication::ThreadDestroyed(ThreadID threadID){ From 18b62d4d1cb9a93cfe04327e47f680635187222e Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Tue, 1 Dec 2015 19:26:00 +1100 Subject: [PATCH 08/41] update message #372 [skipci] --- build/version.build | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/version.build b/build/version.build index 7a0a9a40e..3202eb215 100644 --- a/build/version.build +++ b/build/version.build @@ -2,7 +2,7 @@ - + @@ -10,8 +10,8 @@ - + @@ -37,4 +37,4 @@ - \ No newline at end of file + From 23f0268f0760edf00c09d7e3d1ae8cd9cbfd0d04 Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Tue, 1 Dec 2015 19:28:07 +1100 Subject: [PATCH 09/41] update readme #372 [skipci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 70a0d0961..7d4fd890f 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ You will need: 1. Visual Studio VS2013 (Community Edition) or later with C# and C++ 2. WiX 3.9 or later (http://wix.codeplex.com/releases/view/136891) 3. Specflow (http://visualstudiogallery.msdn.microsoft.com/9915524d-7fb0-43c3-bb3c-a8a14fbd40ee) +4. Windows SDK 8 and .NET Framework Tools (https://msdn.microsoft.com/en-us/windows/desktop/bg162891.aspx) All other software should be included with this repository. From f463cc216e506c05aed8a76a85dc8eb06778a42c Mon Sep 17 00:00:00 2001 From: sawilde Date: Tue, 1 Dec 2015 20:58:15 +1100 Subject: [PATCH 10/41] #335 allow short wait time to be configured more housekeeping --- main/OpenCover.Profiler/CodeCoverage.cpp | 90 ++--- main/OpenCover.Profiler/CodeCoverage.h | 5 +- .../CodeCoverage_Callback.cpp | 8 +- .../CodeCoverage_Thread.cpp | 4 +- .../ProfilerCommunication.cpp | 344 +++++++++--------- .../ProfilerCommunication.h | 49 +-- 6 files changed, 256 insertions(+), 244 deletions(-) diff --git a/main/OpenCover.Profiler/CodeCoverage.cpp b/main/OpenCover.Profiler/CodeCoverage.cpp index 79718f342..d16f9b25b 100644 --- a/main/OpenCover.Profiler/CodeCoverage.cpp +++ b/main/OpenCover.Profiler/CodeCoverage.cpp @@ -10,7 +10,7 @@ #include "NativeCallback.h" #include "dllmain.h" -CCodeCoverage* CCodeCoverage::g_pProfiler = NULL; +CCodeCoverage* CCodeCoverage::g_pProfiler = nullptr; // CCodeCoverage /// Handle ICorProfilerCallback::Initialize @@ -30,7 +30,7 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ //::OutputDebugStringW(szGuid); WCHAR szExeName[MAX_PATH]; - GetModuleFileNameW(NULL, szExeName, MAX_PATH); + GetModuleFileNameW(nullptr, szExeName, MAX_PATH); RELTRACE(L" ::Initialize(...) => EXE = %s", szExeName); WCHAR szModuleName[MAX_PATH]; @@ -38,31 +38,31 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ RELTRACE(L" ::Initialize(...) => PROFILER = %s", szModuleName); //::OutputDebugStringW(szModuleName); - if (g_pProfiler!=NULL) + if (g_pProfiler!=nullptr) RELTRACE(_T("Another instance of the profiler is running under this process...")); m_profilerInfo = pICorProfilerInfoUnk; - if (m_profilerInfo != NULL) ATLTRACE(_T(" ::Initialize (m_profilerInfo OK)")); - if (m_profilerInfo == NULL) return E_FAIL; + if (m_profilerInfo != nullptr) ATLTRACE(_T(" ::Initialize (m_profilerInfo OK)")); + if (m_profilerInfo == nullptr) return E_FAIL; m_profilerInfo2 = pICorProfilerInfoUnk; - if (m_profilerInfo2 != NULL) ATLTRACE(_T(" ::Initialize (m_profilerInfo2 OK)")); - if (m_profilerInfo2 == NULL) return E_FAIL; + if (m_profilerInfo2 != nullptr) ATLTRACE(_T(" ::Initialize (m_profilerInfo2 OK)")); + if (m_profilerInfo2 == nullptr) return E_FAIL; m_profilerInfo3 = pICorProfilerInfoUnk; #ifndef _TOOLSETV71 m_profilerInfo4 = pICorProfilerInfoUnk; #endif ZeroMemory(&m_runtimeVersion, sizeof(m_runtimeVersion)); - if (m_profilerInfo3 != NULL) + if (m_profilerInfo3 != nullptr) { ATLTRACE(_T(" ::Initialize (m_profilerInfo3 OK)")); ZeroMemory(&m_runtimeVersion, sizeof(m_runtimeVersion)); - m_profilerInfo3->GetRuntimeInformation(NULL, &m_runtimeType, + m_profilerInfo3->GetRuntimeInformation(nullptr, &m_runtimeType, &m_runtimeVersion.usMajorVersion, &m_runtimeVersion.usMinorVersion, &m_runtimeVersion.usBuildNumber, - &m_runtimeVersion.usRevisionNumber, 0, NULL, NULL); + &m_runtimeVersion.usRevisionNumber, 0, nullptr, nullptr); ATLTRACE(_T(" ::Initialize (Runtime %d)"), m_runtimeType); } @@ -81,7 +81,7 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ TCHAR threshold[1024] = {0}; ::GetEnvironmentVariable(_T("OpenCover_Profiler_Threshold"), threshold, 1024); - m_threshold = _tcstoul(threshold, NULL, 10); + m_threshold = _tcstoul(threshold, nullptr, 10); ATLTRACE(_T(" ::Initialize(...) => threshold = %ul"), m_threshold); TCHAR tracebyTest[1024] = {0}; @@ -89,10 +89,21 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ m_tracingEnabled = _tcslen(tracebyTest) != 0; ATLTRACE(_T(" ::Initialize(...) => tracingEnabled = %s (%s)"), m_tracingEnabled ? _T("true") : _T("false"), tracebyTest); + TCHAR shortwait[1024] = { 0 }; + if (::GetEnvironmentVariable(_T("OpenCover_Profiler_ShortWait"), shortwait, 1024) > 0) { + _shortwait = _tcstoul(shortwait, nullptr, 10); + if (_shortwait < 10000) + _shortwait = 10000; + if (_shortwait > 60000) + _shortwait = 60000; + ATLTRACE(_T(" ::Initialize(...) => shortwait = %ul"), _shortwait); + } m_useOldStyle = (tstring(instrumentation) == _T("oldSchool")); - if (!m_host.Initialise(key, ns, szExeName)) + _host = std::make_shared(ProfilerCommunication(_shortwait)); + + if (!_host->Initialise(key, ns, szExeName)) { RELTRACE(_T(" ::Initialize => Profiler will not run for this process.")); return E_FAIL; @@ -100,14 +111,14 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ OpenCoverSupportInitialize(pICorProfilerInfoUnk); - if (m_chainedProfiler == NULL){ + if (m_chainedProfiler == nullptr){ DWORD dwMask = AppendProfilerEventMask(0); COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->SetEventMask(dwMask), _T(" ::Initialize(...) => SetEventMask => 0x%X")); } - if(m_profilerInfo3 != NULL) + if(m_profilerInfo3 != nullptr) { COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo3->SetFunctionIDMapper2(FunctionMapper2, this), _T(" ::Initialize(...) => SetFunctionIDMapper2 => 0x%X")); @@ -146,7 +157,7 @@ DWORD CCodeCoverage::AppendProfilerEventMask(DWORD currentEventMask) dwMask |= COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST; // Disables security transparency checks that are normally done during just-in-time (JIT) compilation and class loading for full-trust assemblies. This can make some instrumentation easier to perform. #ifndef _TOOLSETV71 - if (m_profilerInfo4 != NULL) + if (m_profilerInfo4 != nullptr) { ATLTRACE(_T(" ::Initialize (m_profilerInfo4 OK)")); dwMask |= COR_PRF_DISABLE_ALL_NGEN_IMAGES; @@ -163,15 +174,15 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::Shutdown( void) { RELTRACE(_T("::Shutdown - Starting")); - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->Shutdown(); - m_host.CloseChannel(m_tracingEnabled); + _host->CloseChannel(m_tracingEnabled); WCHAR szExeName[MAX_PATH]; - GetModuleFileNameW(NULL, szExeName, MAX_PATH); + GetModuleFileNameW(nullptr, szExeName, MAX_PATH); RELTRACE(_T("::Shutdown - Nothing left to do but return S_OK(%s)"), szExeName); - g_pProfiler = NULL; + g_pProfiler = nullptr; return S_OK; } @@ -197,10 +208,10 @@ void __fastcall CCodeCoverage::AddVisitPoint(ULONG uniqueId) } if (m_tracingEnabled){ - m_host.AddVisitPoint(uniqueId); + _host->AddVisitPoint(uniqueId); } else { - m_host.AddVisitPointToThreadBuffer(uniqueId, IT_VisitPoint); + _host->AddVisitPointToThreadBuffer(uniqueId, IT_VisitPoint); } } @@ -215,7 +226,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ModuleLoadFinished( /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus) { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->ModuleLoadFinished(moduleId, hrStatus); return RegisterCuckoos(moduleId); @@ -228,7 +239,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ModuleAttachedToAssembly( /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID assemblyId) { - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) m_chainedProfiler->ModuleAttachedToAssembly(moduleId, assemblyId); std::wstring modulePath = GetModulePath(moduleId); @@ -236,7 +247,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ModuleAttachedToAssembly( /*ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)"), moduleId, W2CT(modulePath.c_str()), assemblyId, W2CT(assemblyName.c_str()));*/ - m_allowModules[modulePath] = m_host.TrackAssembly((LPWSTR)modulePath.c_str(), (LPWSTR)assemblyName.c_str()); + m_allowModules[modulePath] = _host->TrackAssembly(const_cast(modulePath.c_str()), const_cast(assemblyName.c_str())); m_allowModulesAssemblyMap[modulePath] = assemblyName; if (m_allowModules[modulePath]){ @@ -273,19 +284,17 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( std::vector seqPoints; std::vector brPoints; - if (m_host.GetPoints(functionToken, (LPWSTR)modulePath.c_str(), - (LPWSTR)m_allowModulesAssemblyMap[modulePath].c_str(), seqPoints, brPoints)) + if (_host->GetPoints(functionToken, const_cast(modulePath.c_str()), + const_cast(m_allowModulesAssemblyMap[modulePath].c_str()), seqPoints, brPoints)) { if (seqPoints.size() != 0) { - LPCBYTE pMethodHeader = NULL; + IMAGE_COR_ILMETHOD* pMethodHeader = nullptr; ULONG iMethodSize = 0; - COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->GetILFunctionBody(moduleId, functionToken, &pMethodHeader, &iMethodSize), + COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->GetILFunctionBody(moduleId, functionToken, (LPCBYTE*)&pMethodHeader, &iMethodSize), _T(" ::JITCompilationStarted(...) => GetILFunctionBody => 0x%X")); - IMAGE_COR_ILMETHOD* pMethod = (IMAGE_COR_ILMETHOD*)pMethodHeader; - - Method instumentedMethod(pMethod); + Method instumentedMethod(pMethodHeader); instumentedMethod.IncrementStackSize(2); ATLTRACE(_T("::JITCompilationStarted(...) => Instrumenting...")); @@ -301,13 +310,13 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->GetILFunctionBodyAllocator(moduleId, &methodMalloc), _T(" ::JITCompilationStarted(...) => GetILFunctionBodyAllocator=> 0x%X")); - IMAGE_COR_ILMETHOD* pNewMethod = (IMAGE_COR_ILMETHOD*)methodMalloc->Alloc(instumentedMethod.GetMethodSize()); + auto pNewMethod = static_cast(methodMalloc->Alloc(instumentedMethod.GetMethodSize())); instumentedMethod.WriteMethod(pNewMethod); COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->SetILFunctionBody(moduleId, functionToken, (LPCBYTE)pNewMethod), _T(" ::JITCompilationStarted(...) => SetILFunctionBody => 0x%X")); ULONG mapSize = instumentedMethod.GetILMapSize(); - COR_IL_MAP * pMap = (COR_IL_MAP *)CoTaskMemAlloc(mapSize * sizeof(COR_IL_MAP)); + COR_IL_MAP * pMap = static_cast(CoTaskMemAlloc(mapSize * sizeof(COR_IL_MAP))); instumentedMethod.PopulateILMap(mapSize, pMap); COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->SetILInstrumentedCodeMap(functionId, TRUE, mapSize, pMap), _T(" ::JITCompilationStarted(...) => SetILInstrumentedCodeMap => 0x%X")); @@ -329,7 +338,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( } } - if (m_chainedProfiler != NULL) + if (m_chainedProfiler != nullptr) return m_chainedProfiler->JITCompilationStarted(functionId, fIsSafeToBlock); return S_OK; @@ -343,8 +352,8 @@ void CCodeCoverage::InstrumentMethod(ModuleID moduleId, Method& method, std::ve { if (m_useOldStyle) { - mdSignature pvsig = GetMethodSignatureToken_I4(moduleId); - void(__fastcall *pt)(ULONG) = GetInstrumentPointVisit(); + auto pvsig = GetMethodSignatureToken_I4(moduleId); + auto pt = GetInstrumentPointVisit(); InstructionList instructions; if (seqPoints.size() > 0) @@ -384,13 +393,12 @@ void CCodeCoverage::InstrumentMethod(ModuleID moduleId, Method& method, std::ve HRESULT CCodeCoverage::InstrumentMethodWith(ModuleID moduleId, mdToken functionToken, InstructionList &instructions){ - LPCBYTE pMethodHeader = NULL; + IMAGE_COR_ILMETHOD* pMethodHeader = nullptr; ULONG iMethodSize = 0; - COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo->GetILFunctionBody(moduleId, functionToken, &pMethodHeader, &iMethodSize), + COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo->GetILFunctionBody(moduleId, functionToken, (LPCBYTE*)&pMethodHeader, &iMethodSize), _T(" ::InstrumentMethodWith(...) => GetILFunctionBody => 0x%X")); - IMAGE_COR_ILMETHOD* pMethod = (IMAGE_COR_ILMETHOD*)pMethodHeader; - Method instumentedMethod(pMethod); + Method instumentedMethod(pMethodHeader); instumentedMethod.InsertInstructionsAtOriginalOffset(0, instructions); @@ -401,7 +409,7 @@ HRESULT CCodeCoverage::InstrumentMethodWith(ModuleID moduleId, mdToken functionT COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo->GetILFunctionBodyAllocator(moduleId, &methodMalloc), _T(" ::InstrumentMethodWith(...) => GetILFunctionBodyAllocator=> 0x%X")); - IMAGE_COR_ILMETHOD* pNewMethod = (IMAGE_COR_ILMETHOD*)methodMalloc->Alloc(instumentedMethod.GetMethodSize()); + IMAGE_COR_ILMETHOD* pNewMethod = static_cast(methodMalloc->Alloc(instumentedMethod.GetMethodSize())); instumentedMethod.WriteMethod(pNewMethod); COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo->SetILFunctionBody(moduleId, functionToken, (LPCBYTE)pNewMethod), _T(" ::InstrumentMethodWith(...) => SetILFunctionBody => 0x%X")); diff --git a/main/OpenCover.Profiler/CodeCoverage.h b/main/OpenCover.Profiler/CodeCoverage.h index a5241f3ab..18dd148ee 100644 --- a/main/OpenCover.Profiler/CodeCoverage.h +++ b/main/OpenCover.Profiler/CodeCoverage.h @@ -17,6 +17,7 @@ #include #include "ReleaseTrace.h" +#include using namespace ATL; @@ -52,6 +53,7 @@ class ATL_NO_VTABLE CCodeCoverage : m_cuckooCriticalToken = 0; m_cuckooSafeToken = 0; m_infoHook = nullptr; + _shortwait = 10000; } DECLARE_REGISTRY_RESOURCEID(IDR_CODECOVERAGE) @@ -99,7 +101,8 @@ END_COM_MAP() void __fastcall AddVisitPoint(ULONG uniqueId); private: - ProfilerCommunication m_host; + std::shared_ptr _host; + ULONG _shortwait; HRESULT OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk); DWORD AppendProfilerEventMask(DWORD currentEventMask); diff --git a/main/OpenCover.Profiler/CodeCoverage_Callback.cpp b/main/OpenCover.Profiler/CodeCoverage_Callback.cpp index bfbdd4be5..d92b0b59f 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Callback.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Callback.cpp @@ -24,7 +24,7 @@ UINT_PTR CCodeCoverage::FunctionMapper2(FunctionID functionId, void* clientData, if (profiler->GetTokenAndModule(functionId, functionToken, moduleId, modulePath, &assemblyId)) { ULONG uniqueId; - if (profiler->m_host.TrackMethod(functionToken, (LPWSTR)modulePath.c_str(), + if (profiler->_host->TrackMethod(functionToken, (LPWSTR)modulePath.c_str(), (LPWSTR)profiler->m_allowModulesAssemblyMap[modulePath].c_str(), uniqueId)) { *pbHookFunction = TRUE; @@ -46,7 +46,7 @@ void CCodeCoverage::FunctionEnter2( /*[in]*/COR_PRF_FRAME_INFO func, /*[in]*/COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo) { - m_host.AddTestEnterPoint((ULONG)clientData); + _host->AddTestEnterPoint((ULONG)clientData); } void CCodeCoverage::FunctionLeave2( @@ -55,7 +55,7 @@ void CCodeCoverage::FunctionLeave2( /*[in]*/COR_PRF_FRAME_INFO func, /*[in]*/COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange) { - m_host.AddTestLeavePoint((ULONG)clientData); + _host->AddTestLeavePoint((ULONG)clientData); } void CCodeCoverage::FunctionTailcall2( @@ -63,5 +63,5 @@ void CCodeCoverage::FunctionTailcall2( /*[in]*/UINT_PTR clientData, /*[in]*/COR_PRF_FRAME_INFO func) { - m_host.AddTestTailcallPoint((ULONG)clientData); + _host->AddTestTailcallPoint((ULONG)clientData); } diff --git a/main/OpenCover.Profiler/CodeCoverage_Thread.cpp b/main/OpenCover.Profiler/CodeCoverage_Thread.cpp index 62b37ec1e..18b9c7192 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Thread.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Thread.cpp @@ -21,7 +21,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadDestroyed( m_chainedProfiler->ThreadDestroyed(threadId); if (!m_tracingEnabled){ - m_host.ThreadDestroyed(threadId); + _host->ThreadDestroyed(threadId); } return S_OK; @@ -36,7 +36,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ThreadAssignedToOSThread( m_chainedProfiler->ThreadAssignedToOSThread(managedThreadId, osThreadId); if (!m_tracingEnabled){ - m_host.ThreadCreated(managedThreadId, osThreadId); + _host->ThreadCreated(managedThreadId, osThreadId); } return S_OK; diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp index 620ba9583..e240b520e 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.cpp +++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp @@ -13,16 +13,16 @@ #include #define ONERROR_GOEXIT(hr) if (FAILED(hr)) goto Exit -#define COMM_WAIT_SHORT 10000 -#define COMM_WAIT_LONG 60000 -#define COMM_WAIT_VSHORT 3000 +#define COM_WAIT_LONG 60000 +#define COM_WAIT_VSHORT 3000 -ProfilerCommunication::ProfilerCommunication() +ProfilerCommunication::ProfilerCommunication(DWORD short_wait) { - m_bufferId = 0; - m_pMSG = nullptr; - m_pVisitPoints = nullptr; - hostCommunicationActive = false; + _bufferId = 0; + _pMSG = nullptr; + _pVisitPoints = nullptr; + _hostCommunicationActive = false; + _short_wait = short_wait; } ProfilerCommunication::~ProfilerCommunication() @@ -31,57 +31,57 @@ ProfilerCommunication::~ProfilerCommunication() bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName) { - m_key = key; - m_processName = processName; + _key = key; + _processName = processName; std::wstring sharedKey = key; sharedKey.append(_T("-1")); - m_namespace = ns; + _namespace = ns; - m_mutexCommunication.Initialise((m_namespace + _T("\\OpenCover_Profiler_Communication_Mutex_") + m_key).c_str()); - if (!m_mutexCommunication.IsValid()) return false; + _mutexCommunication.Initialise((_namespace + _T("\\OpenCover_Profiler_Communication_Mutex_") + _key).c_str()); + if (!_mutexCommunication.IsValid()) return false; USES_CONVERSION; ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised mutexes => %s"), W2CT(sharedKey.c_str())); - auto resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + sharedKey); - m_eventProfilerRequestsInformation.Initialise(resource_name.c_str()); - if (!m_eventProfilerRequestsInformation.IsValid()) { + auto resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + sharedKey); + _eventProfilerRequestsInformation.Initialise(resource_name.c_str()); + if (!_eventProfilerRequestsInformation.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ChunkData_Event_") + sharedKey); - m_eventInformationReadByProfiler.Initialise(resource_name.c_str()); - if (!m_eventInformationReadByProfiler.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_ChunkData_Event_") + sharedKey); + _eventInformationReadByProfiler.Initialise(resource_name.c_str()); + if (!_eventInformationReadByProfiler.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) = >Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ReceiveData_Event_") + sharedKey); - m_eventInformationReadyForProfiler.Initialise(resource_name.c_str()); - if (!m_eventInformationReadyForProfiler.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_ReceiveData_Event_") + sharedKey); + _eventInformationReadyForProfiler.Initialise(resource_name.c_str()); + if (!_eventInformationReadyForProfiler.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_MemoryMapFile_") + sharedKey); - m_memoryCommunication.OpenFileMapping(resource_name.c_str()); - if (!m_memoryCommunication.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_MemoryMapFile_") + sharedKey); + _memoryCommunication.OpenFileMapping(resource_name.c_str()); + if (!_memoryCommunication.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_Semaphore_") + sharedKey); + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_Semaphore_") + sharedKey); _semapore_communication.Initialise(resource_name.c_str()); if (!_semapore_communication.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); return false; } - m_pMSG = (MSG_Union*)m_memoryCommunication.MapViewOfFile(0, 0, MAX_MSG_SIZE); + _pMSG = static_cast(_memoryCommunication.MapViewOfFile(0, 0, MAX_MSG_SIZE)); - hostCommunicationActive = true; + _hostCommunicationActive = true; ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised communication interface => %s"), W2CT(sharedKey.c_str())); @@ -98,104 +98,104 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName stream << bufferId; stream >> memoryKey; - m_bufferId = bufferId; + _bufferId = bufferId; - memoryKey = m_key + memoryKey; + memoryKey = _key + memoryKey; ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Re-initialising communication interface => %s"), W2CT(memoryKey.c_str())); - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + memoryKey); - m_eventProfilerRequestsInformation.Initialise(resource_name.c_str()); - if (!m_eventProfilerRequestsInformation.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_SendData_Event_") + memoryKey); + _eventProfilerRequestsInformation.Initialise(resource_name.c_str()); + if (!_eventProfilerRequestsInformation.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ChunkData_Event_") + memoryKey); - m_eventInformationReadByProfiler.Initialise(resource_name.c_str()); - if (!m_eventInformationReadByProfiler.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_ChunkData_Event_") + memoryKey); + _eventInformationReadByProfiler.Initialise(resource_name.c_str()); + if (!_eventInformationReadByProfiler.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_ReceiveData_Event_") + memoryKey); - m_eventInformationReadyForProfiler.Initialise(resource_name.c_str()); - if (!m_eventInformationReadyForProfiler.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_ReceiveData_Event_") + memoryKey); + _eventInformationReadyForProfiler.Initialise(resource_name.c_str()); + if (!_eventInformationReadyForProfiler.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_MemoryMapFile_") + memoryKey); - m_memoryCommunication.OpenFileMapping(resource_name.c_str()); - if (!m_memoryCommunication.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_MemoryMapFile_") + memoryKey); + _memoryCommunication.OpenFileMapping(resource_name.c_str()); + if (!_memoryCommunication.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - m_pMSG = (MSG_Union*)m_memoryCommunication.MapViewOfFile(0, 0, MAX_MSG_SIZE); + _pMSG = static_cast(_memoryCommunication.MapViewOfFile(0, 0, MAX_MSG_SIZE)); - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Communication_Semaphore_") + memoryKey); + resource_name = (_namespace + _T("\\OpenCover_Profiler_Communication_Semaphore_") + memoryKey); _semapore_communication.Initialise(resource_name.c_str()); if (!_semapore_communication.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } ATLTRACE(_T("ProfilerCommunication::Initialise(...) => Re-initialised communication interface => %s"), W2CT(memoryKey.c_str())); - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_SendResults_Event_") + memoryKey); - m_eventProfilerHasResults.Initialise(resource_name.c_str()); - if (!m_eventProfilerHasResults.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Results_SendResults_Event_") + memoryKey); + _eventProfilerHasResults.Initialise(resource_name.c_str()); + if (!_eventProfilerHasResults.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_ReceiveResults_Event_") + memoryKey); - m_eventResultsHaveBeenReceived.Initialise(resource_name.c_str()); - if (!m_eventResultsHaveBeenReceived.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Results_ReceiveResults_Event_") + memoryKey); + _eventResultsHaveBeenReceived.Initialise(resource_name.c_str()); + if (!_eventResultsHaveBeenReceived.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_MemoryMapFile_") + memoryKey); - m_memoryResults.OpenFileMapping(resource_name.c_str()); - if (!m_memoryResults.IsValid()) { + resource_name = (_namespace + _T("\\OpenCover_Profiler_Results_MemoryMapFile_") + memoryKey); + _memoryResults.OpenFileMapping(resource_name.c_str()); + if (!_memoryResults.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } - m_pVisitPoints = (MSG_SendVisitPoints_Request*)m_memoryResults.MapViewOfFile(0, 0, MAX_MSG_SIZE); + _pVisitPoints = static_cast(_memoryResults.MapViewOfFile(0, 0, MAX_MSG_SIZE)); - m_pVisitPoints->count = 0; + _pVisitPoints->count = 0; - resource_name = (m_namespace + _T("\\OpenCover_Profiler_Results_Semaphore_") + memoryKey); + resource_name = (_namespace + _T("\\OpenCover_Profiler_Results_Semaphore_") + memoryKey); _semapore_results.Initialise(resource_name.c_str()); if (!_semapore_results.IsValid()) { RELTRACE(_T("ProfilerCommunication::Initialise(...) => Failed to initialise resource %s => ::GetLastError() = %d"), W2CT(resource_name.c_str()), ::GetLastError()); - hostCommunicationActive = false; + _hostCommunicationActive = false; return false; } RELTRACE(_T("ProfilerCommunication::Initialise(...) => Initialised results interface => %s"), W2CT(memoryKey.c_str())); } else { - hostCommunicationActive = false; + _hostCommunicationActive = false; } - return hostCommunicationActive; + return _hostCommunicationActive; } void ProfilerCommunication::ThreadCreated(ThreadID threadID, DWORD osThreadID){ - ATL::CComCritSecLock lock(m_critThreads); - m_threadmap[threadID] = osThreadID; + ATL::CComCritSecLock lock(_critThreads); + _threadmap[threadID] = osThreadID; AllocateVisitMap(osThreadID); } @@ -203,14 +203,14 @@ MSG_SendVisitPoints_Request* ProfilerCommunication::AllocateVisitMap(DWORD osThr auto p = new MSG_SendVisitPoints_Request(); p->count = 0; //::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request)); - m_visitmap[osThreadID] = p; + _visitmap[osThreadID] = p; return p; } MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG osThreadID){ MSG_SendVisitPoints_Request * p; try { - p = m_visitmap[osThreadID]; + p = _visitmap[osThreadID]; if (p == nullptr) p = AllocateVisitMap(osThreadID); } @@ -221,18 +221,18 @@ MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG } void ProfilerCommunication::ThreadDestroyed(ThreadID threadID){ - ATL::CComCritSecLock lock(m_critThreads); - ULONG osThreadId = m_threadmap[threadID]; - auto points = m_visitmap[osThreadId]; + ATL::CComCritSecLock lock(_critThreads); + ULONG osThreadId = _threadmap[threadID]; + auto points = _visitmap[osThreadId]; SendThreadVisitPoints(points); - delete m_visitmap[osThreadId]; - m_visitmap[osThreadId] = NULL; + delete _visitmap[osThreadId]; + _visitmap[osThreadId] = nullptr; } void ProfilerCommunication::SendRemainingThreadBuffers(){ - ATL::CComCritSecLock lock(m_critThreads); - for (auto it = m_visitmap.begin(); it != m_visitmap.end(); ++it){ - if (it->second != NULL){ + ATL::CComCritSecLock lock(_critThreads); + for (auto it = _visitmap.begin(); it != _visitmap.end(); ++it){ + if (it->second != nullptr){ SendThreadVisitPoints(it->second); //::ZeroMemory(pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); } @@ -252,62 +252,62 @@ void ProfilerCommunication::AddVisitPointToThreadBuffer(ULONG uniqueId, MSG_IdTy } void ProfilerCommunication::SendThreadVisitPoints(MSG_SendVisitPoints_Request* pVisitPoints){ - ATL::CComCritSecLock lock(m_critResults); + ATL::CComCritSecLock lock(_critResults); - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return; if (!TestSemaphore(_semapore_results)) return; handle_exception([=](){ - memcpy(m_pVisitPoints, pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); + memcpy(_pVisitPoints, pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); }, _T("SendThreadVisitPoints")); pVisitPoints->count = 0; SendVisitPoints(); - //::ZeroMemory(m_pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); - m_pVisitPoints->count = 0; + //::ZeroMemory(_pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); + _pVisitPoints->count = 0; } void ProfilerCommunication::AddVisitPointToBuffer(ULONG uniqueId, MSG_IdType msgType) { - ATL::CComCritSecLock lock(m_critResults); + ATL::CComCritSecLock lock(_critResults); - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return; if (!TestSemaphore(_semapore_results)) return; handle_exception([=](){ - m_pVisitPoints->points[m_pVisitPoints->count].UniqueId = (uniqueId | msgType); + _pVisitPoints->points[_pVisitPoints->count].UniqueId = (uniqueId | msgType); }, _T("AddVisitPointToBuffer")); - if (++m_pVisitPoints->count == VP_BUFFER_SIZE) + if (++_pVisitPoints->count == VP_BUFFER_SIZE) { SendVisitPoints(); - //::ZeroMemory(m_pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); + //::ZeroMemory(_pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); handle_exception([=](){ - m_pVisitPoints->count = 0; + _pVisitPoints->count = 0; }, _T("AddVisitPointToBuffer")); } } void ProfilerCommunication::SendVisitPoints() { - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return; try { - m_memoryResults.FlushViewOfFile(); + _memoryResults.FlushViewOfFile(); - DWORD dwSignal = m_eventProfilerHasResults.SignalAndWait(m_eventResultsHaveBeenReceived, COMM_WAIT_SHORT); - if (WAIT_OBJECT_0 != dwSignal) throw CommunicationException(dwSignal, COMM_WAIT_SHORT); - m_eventResultsHaveBeenReceived.Reset(); + DWORD dwSignal = _eventProfilerHasResults.SignalAndWait(_eventResultsHaveBeenReceived, _short_wait); + if (WAIT_OBJECT_0 != dwSignal) throw CommunicationException(dwSignal, _short_wait); + _eventResultsHaveBeenReceived.Reset(); } catch (CommunicationException ex) { RELTRACE(_T("ProfilerCommunication::SendVisitPoints() => Communication (Results channel) with host has failed (0x%x, %d)"), ex.getReason(), ex.getTimeout()); - hostCommunicationActive = false; + _hostCommunicationActive = false; } return; } @@ -329,35 +329,35 @@ bool ProfilerCommunication::GetPoints(mdToken functionToken, WCHAR* pModulePath, bool ProfilerCommunication::GetSequencePoints(mdToken functionToken, WCHAR* pModulePath, WCHAR* pAssemblyName, std::vector &points) { - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return false; RequestInformation( [=] { - m_pMSG->getSequencePointsRequest.type = MSG_GetSequencePoints; - m_pMSG->getSequencePointsRequest.functionToken = functionToken; + _pMSG->getSequencePointsRequest.type = MSG_GetSequencePoints; + _pMSG->getSequencePointsRequest.functionToken = functionToken; USES_CONVERSION; - wcscpy_s(m_pMSG->getSequencePointsRequest.szProcessName, T2CW(m_processName.c_str())); - wcscpy_s(m_pMSG->getSequencePointsRequest.szModulePath, pModulePath); - wcscpy_s(m_pMSG->getSequencePointsRequest.szAssemblyName, pAssemblyName); + wcscpy_s(_pMSG->getSequencePointsRequest.szProcessName, T2CW(_processName.c_str())); + wcscpy_s(_pMSG->getSequencePointsRequest.szModulePath, pModulePath); + wcscpy_s(_pMSG->getSequencePointsRequest.szAssemblyName, pAssemblyName); }, [=, &points]()->BOOL { - if (m_pMSG->getSequencePointsResponse.count > SEQ_BUFFER_SIZE){ + if (_pMSG->getSequencePointsResponse.count > SEQ_BUFFER_SIZE){ RELTRACE(_T("Received an abnormal count for sequence points (%d) for token 0x%X"), - m_pMSG->getSequencePointsResponse.count, functionToken); + _pMSG->getSequencePointsResponse.count, functionToken); points.clear(); return false; } - for (int i = 0; i < m_pMSG->getSequencePointsResponse.count; i++) - points.push_back(m_pMSG->getSequencePointsResponse.points[i]); - BOOL hasMore = m_pMSG->getSequencePointsResponse.hasMore; - ::ZeroMemory(m_pMSG, MAX_MSG_SIZE); + for (int i = 0; i < _pMSG->getSequencePointsResponse.count; i++) + points.push_back(_pMSG->getSequencePointsResponse.points[i]); + BOOL hasMore = _pMSG->getSequencePointsResponse.hasMore; + ::ZeroMemory(_pMSG, MAX_MSG_SIZE); return hasMore; } - , COMM_WAIT_SHORT + , _short_wait , _T("GetSequencePoints")); return (points.size() != 0); @@ -366,35 +366,35 @@ bool ProfilerCommunication::GetSequencePoints(mdToken functionToken, WCHAR* pMod bool ProfilerCommunication::GetBranchPoints(mdToken functionToken, WCHAR* pModulePath, WCHAR* pAssemblyName, std::vector &points) { - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return false; RequestInformation( [=] { - m_pMSG->getBranchPointsRequest.type = MSG_GetBranchPoints; - m_pMSG->getBranchPointsRequest.functionToken = functionToken; + _pMSG->getBranchPointsRequest.type = MSG_GetBranchPoints; + _pMSG->getBranchPointsRequest.functionToken = functionToken; USES_CONVERSION; - wcscpy_s(m_pMSG->getBranchPointsRequest.szProcessName, T2CW(m_processName.c_str())); - wcscpy_s(m_pMSG->getBranchPointsRequest.szModulePath, pModulePath); - wcscpy_s(m_pMSG->getBranchPointsRequest.szAssemblyName, pAssemblyName); + wcscpy_s(_pMSG->getBranchPointsRequest.szProcessName, T2CW(_processName.c_str())); + wcscpy_s(_pMSG->getBranchPointsRequest.szModulePath, pModulePath); + wcscpy_s(_pMSG->getBranchPointsRequest.szAssemblyName, pAssemblyName); }, [=, &points]()->BOOL { - if (m_pMSG->getBranchPointsResponse.count > BRANCH_BUFFER_SIZE){ + if (_pMSG->getBranchPointsResponse.count > BRANCH_BUFFER_SIZE){ RELTRACE(_T("Received an abnormal count for branch points (%d) for token 0x%X"), - m_pMSG->getBranchPointsResponse.count, functionToken); + _pMSG->getBranchPointsResponse.count, functionToken); points.clear(); return false; } - for (int i=0; i < m_pMSG->getBranchPointsResponse.count;i++) - points.push_back(m_pMSG->getBranchPointsResponse.points[i]); - BOOL hasMore = m_pMSG->getBranchPointsResponse.hasMore; - ::ZeroMemory(m_pMSG, MAX_MSG_SIZE); + for (int i=0; i < _pMSG->getBranchPointsResponse.count;i++) + points.push_back(_pMSG->getBranchPointsResponse.points[i]); + BOOL hasMore = _pMSG->getBranchPointsResponse.hasMore; + ::ZeroMemory(_pMSG, MAX_MSG_SIZE); return hasMore; } - , COMM_WAIT_SHORT + , _short_wait , _T("GetBranchPoints")); return (points.size() != 0); @@ -402,26 +402,26 @@ bool ProfilerCommunication::GetBranchPoints(mdToken functionToken, WCHAR* pModul bool ProfilerCommunication::TrackAssembly(WCHAR* pModulePath, WCHAR* pAssemblyName) { - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return false; bool response = false; RequestInformation( [=]() { - m_pMSG->trackAssemblyRequest.type = MSG_TrackAssembly; + _pMSG->trackAssemblyRequest.type = MSG_TrackAssembly; USES_CONVERSION; - wcscpy_s(m_pMSG->trackAssemblyRequest.szProcessName, T2CW(m_processName.c_str())); - wcscpy_s(m_pMSG->trackAssemblyRequest.szModulePath, pModulePath); - wcscpy_s(m_pMSG->trackAssemblyRequest.szAssemblyName, pAssemblyName); + wcscpy_s(_pMSG->trackAssemblyRequest.szProcessName, T2CW(_processName.c_str())); + wcscpy_s(_pMSG->trackAssemblyRequest.szModulePath, pModulePath); + wcscpy_s(_pMSG->trackAssemblyRequest.szAssemblyName, pAssemblyName); }, [=, &response]()->BOOL { - response = m_pMSG->trackAssemblyResponse.bResponse == TRUE; - ::ZeroMemory(m_pMSG, MAX_MSG_SIZE); + response = _pMSG->trackAssemblyResponse.bResponse == TRUE; + ::ZeroMemory(_pMSG, MAX_MSG_SIZE); return FALSE; } - , COMM_WAIT_LONG + , COM_WAIT_LONG , _T("TrackAssembly")); return response; @@ -429,26 +429,26 @@ bool ProfilerCommunication::TrackAssembly(WCHAR* pModulePath, WCHAR* pAssemblyNa bool ProfilerCommunication::TrackMethod(mdToken functionToken, WCHAR* pModulePath, WCHAR* pAssemblyName, ULONG &uniqueId) { - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return false; bool response = false; RequestInformation( [=]() { - m_pMSG->trackMethodRequest.type = MSG_TrackMethod; - m_pMSG->trackMethodRequest.functionToken = functionToken; - wcscpy_s(m_pMSG->trackMethodRequest.szModulePath, pModulePath); - wcscpy_s(m_pMSG->trackMethodRequest.szAssemblyName, pAssemblyName); + _pMSG->trackMethodRequest.type = MSG_TrackMethod; + _pMSG->trackMethodRequest.functionToken = functionToken; + wcscpy_s(_pMSG->trackMethodRequest.szModulePath, pModulePath); + wcscpy_s(_pMSG->trackMethodRequest.szAssemblyName, pAssemblyName); }, [=, &response, &uniqueId]()->BOOL { - response = m_pMSG->trackMethodResponse.bResponse == TRUE; - uniqueId = m_pMSG->trackMethodResponse.ulUniqueId; - ::ZeroMemory(m_pMSG, MAX_MSG_SIZE); + response = _pMSG->trackMethodResponse.bResponse == TRUE; + uniqueId = _pMSG->trackMethodResponse.ulUniqueId; + ::ZeroMemory(_pMSG, MAX_MSG_SIZE); return FALSE; } - , COMM_WAIT_SHORT + , _short_wait , _T("TrackMethod")); return response; @@ -456,29 +456,29 @@ bool ProfilerCommunication::TrackMethod(mdToken functionToken, WCHAR* pModulePat bool ProfilerCommunication::AllocateBuffer(LONG bufferSize, ULONG &bufferId) { - CScopedLock lock(m_mutexCommunication); + CScopedLock lock(_mutexCommunication); - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return false; bool response = false; int repeat = 0; while (!response && (++repeat <= 3)){ - hostCommunicationActive = true; + _hostCommunicationActive = true; RequestInformation( [=]() { - m_pMSG->allocateBufferRequest.type = MSG_AllocateMemoryBuffer; - m_pMSG->allocateBufferRequest.lBufferSize = bufferSize; + _pMSG->allocateBufferRequest.type = MSG_AllocateMemoryBuffer; + _pMSG->allocateBufferRequest.lBufferSize = bufferSize; }, [=, &response, &bufferId]()->BOOL { - response = m_pMSG->allocateBufferResponse.bResponse == TRUE; - bufferId = m_pMSG->allocateBufferResponse.ulBufferId; - ::ZeroMemory(m_pMSG, MAX_MSG_SIZE); + response = _pMSG->allocateBufferResponse.bResponse == TRUE; + bufferId = _pMSG->allocateBufferResponse.ulBufferId; + ::ZeroMemory(_pMSG, MAX_MSG_SIZE); return FALSE; } - , COMM_WAIT_VSHORT + , COM_WAIT_VSHORT , _T("AllocateBuffer")); } @@ -486,10 +486,10 @@ bool ProfilerCommunication::AllocateBuffer(LONG bufferSize, ULONG &bufferId) } void ProfilerCommunication::CloseChannel(bool sendSingleBuffer){ - if (m_bufferId == 0) + if (_bufferId == 0) return; - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return; if (!TestSemaphore(_semapore_results)) @@ -500,7 +500,7 @@ void ProfilerCommunication::CloseChannel(bool sendSingleBuffer){ else SendRemainingThreadBuffers(); - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return; bool response = false; @@ -508,24 +508,24 @@ void ProfilerCommunication::CloseChannel(bool sendSingleBuffer){ RequestInformation( [=]() { - m_pMSG->closeChannelRequest.type = MSG_CloseChannel; - m_pMSG->closeChannelRequest.ulBufferId = m_bufferId; + _pMSG->closeChannelRequest.type = MSG_CloseChannel; + _pMSG->closeChannelRequest.ulBufferId = _bufferId; }, [=, &response]()->BOOL { - response = m_pMSG->allocateBufferResponse.bResponse == TRUE; + response = _pMSG->allocateBufferResponse.bResponse == TRUE; return FALSE; } - , COMM_WAIT_SHORT + , _short_wait , _T("CloseChannel")); return; } bool ProfilerCommunication::TrackProcess(){ - CScopedLock lock(m_mutexCommunication); + CScopedLock lock(_mutexCommunication); - if (!hostCommunicationActive) + if (!_hostCommunicationActive) return false; bool response = false; @@ -533,16 +533,16 @@ bool ProfilerCommunication::TrackProcess(){ RequestInformation( [=]() { - m_pMSG->trackProcessRequest.type = MSG_TrackProcess; + _pMSG->trackProcessRequest.type = MSG_TrackProcess; USES_CONVERSION; - wcscpy_s(m_pMSG->trackProcessRequest.szProcessName, T2CW(m_processName.c_str())); + wcscpy_s(_pMSG->trackProcessRequest.szProcessName, T2CW(_processName.c_str())); }, [=, &response]()->BOOL { - response = m_pMSG->trackProcessResponse.bResponse == TRUE; + response = _pMSG->trackProcessResponse.bResponse == TRUE; return FALSE; } - , COMM_WAIT_SHORT + , _short_wait , _T("TrackProcess")); return response; @@ -602,8 +602,8 @@ void ProfilerCommunication::handle_exception(Action action, const tstring& messa template void ProfilerCommunication::RequestInformation(BR buildRequest, PR processResults, DWORD dwTimeout, tstring message) { - ATL::CComCritSecLock lock(m_critComms); - if (!hostCommunicationActive) + ATL::CComCritSecLock lock(_critComms); + if (!_hostCommunicationActive) return; if (!TestSemaphore(_semapore_communication)) @@ -613,12 +613,12 @@ void ProfilerCommunication::RequestInformation(BR buildRequest, PR processResult handle_exception([&](){ buildRequest(); }, message); - m_memoryCommunication.FlushViewOfFile(); + _memoryCommunication.FlushViewOfFile(); - DWORD dwSignal = m_eventProfilerRequestsInformation.SignalAndWait(m_eventInformationReadyForProfiler, dwTimeout); + DWORD dwSignal = _eventProfilerRequestsInformation.SignalAndWait(_eventInformationReadyForProfiler, dwTimeout); if (WAIT_OBJECT_0 != dwSignal) throw CommunicationException(dwSignal, dwTimeout); - m_eventInformationReadyForProfiler.Reset(); + _eventInformationReadyForProfiler.Reset(); BOOL hasMore = FALSE; do @@ -627,21 +627,21 @@ void ProfilerCommunication::RequestInformation(BR buildRequest, PR processResult if (hasMore) { - dwSignal = m_eventInformationReadByProfiler.SignalAndWait(m_eventInformationReadyForProfiler, COMM_WAIT_SHORT); - if (WAIT_OBJECT_0 != dwSignal) throw CommunicationException(dwSignal, COMM_WAIT_SHORT); + dwSignal = _eventInformationReadByProfiler.SignalAndWait(_eventInformationReadyForProfiler, _short_wait); + if (WAIT_OBJECT_0 != dwSignal) throw CommunicationException(dwSignal, _short_wait); - m_eventInformationReadyForProfiler.Reset(); + _eventInformationReadyForProfiler.Reset(); } }while (hasMore); - m_eventInformationReadByProfiler.Set(); + _eventInformationReadByProfiler.Set(); } catch (CommunicationException ex) { RELTRACE(_T("ProfilerCommunication::RequestInformation(...) => Communication (Chat channel - %s) with host has failed (0x%x, %d)"), message.c_str(), ex.getReason(), ex.getTimeout()); - hostCommunicationActive = false; + _hostCommunicationActive = false; } catch (...) { - hostCommunicationActive = false; + _hostCommunicationActive = false; } } diff --git a/main/OpenCover.Profiler/ProfilerCommunication.h b/main/OpenCover.Profiler/ProfilerCommunication.h index 0d5e0518f..c07341d29 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.h +++ b/main/OpenCover.Profiler/ProfilerCommunication.h @@ -20,7 +20,7 @@ class ProfilerCommunication private: public: - ProfilerCommunication(); + ProfilerCommunication(DWORD short_wait); ~ProfilerCommunication(void); bool Initialise(TCHAR* key, TCHAR *ns, TCHAR *processName); @@ -53,49 +53,50 @@ class ProfilerCommunication MSG_SendVisitPoints_Request* AllocateVisitMap(DWORD osThreadID); private: - tstring m_key; - tstring m_namespace; - tstring m_processName; + tstring _key; + tstring _namespace; + tstring _processName; + DWORD _short_wait; template void RequestInformation(BR buildRequest, PR processResults, DWORD dwTimeout, tstring message); - ULONG m_bufferId; + ULONG _bufferId; bool TestSemaphore(CSemaphoreEx &semaphore){ // the previous value should always be zero unless the host process has released // and that means we have disposed of the shared memory - if (hostCommunicationActive && semaphore.ReleaseAndWait() != 0) { - hostCommunicationActive = false; + if (_hostCommunicationActive && semaphore.ReleaseAndWait() != 0) { + _hostCommunicationActive = false; } - return hostCommunicationActive; + return _hostCommunicationActive; } private: - CMutex m_mutexCommunication; - CSharedMemory m_memoryCommunication; - CEvent m_eventProfilerRequestsInformation; - CEvent m_eventInformationReadyForProfiler; - CEvent m_eventInformationReadByProfiler; - MSG_Union *m_pMSG; + CMutex _mutexCommunication; + CSharedMemory _memoryCommunication; + CEvent _eventProfilerRequestsInformation; + CEvent _eventInformationReadyForProfiler; + CEvent _eventInformationReadByProfiler; + MSG_Union *_pMSG; CSemaphoreEx _semapore_communication; private: - CSharedMemory m_memoryResults; - CEvent m_eventProfilerHasResults; - CEvent m_eventResultsHaveBeenReceived; - MSG_SendVisitPoints_Request *m_pVisitPoints; + CSharedMemory _memoryResults; + CEvent _eventProfilerHasResults; + CEvent _eventResultsHaveBeenReceived; + MSG_SendVisitPoints_Request *_pVisitPoints; CSemaphoreEx _semapore_results; private: - ATL::CComAutoCriticalSection m_critResults; - ATL::CComAutoCriticalSection m_critComms; - bool hostCommunicationActive; + ATL::CComAutoCriticalSection _critResults; + ATL::CComAutoCriticalSection _critComms; + bool _hostCommunicationActive; private: - ATL::CComAutoCriticalSection m_critThreads; - std::unordered_map m_threadmap; - std::unordered_map m_visitmap; + ATL::CComAutoCriticalSection _critThreads; + std::unordered_map _threadmap; + std::unordered_map _visitmap; MSG_SendVisitPoints_Request* GetVisitMapForOSThread(ULONG osThread); From 59c8534a11c4ee38c1fb6c7a40cee9bc327b16a0 Mon Sep 17 00:00:00 2001 From: sawilde Date: Wed, 2 Dec 2015 07:55:54 +1100 Subject: [PATCH 11/41] #335 extract communication timeout value --- main/OpenCover.Framework/CommandLineParser.cs | 10 ++++++ .../Framework/CommandLineParserTests.cs | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/main/OpenCover.Framework/CommandLineParser.cs b/main/OpenCover.Framework/CommandLineParser.cs index a6d01570f..339cffc0a 100644 --- a/main/OpenCover.Framework/CommandLineParser.cs +++ b/main/OpenCover.Framework/CommandLineParser.cs @@ -190,6 +190,11 @@ public void ExtractAndValidateArguments() ReturnCodeOffset = ExtractValue("returntargetcode", () => { throw new InvalidOperationException("The return target code offset must be an integer"); }); break; + case "communicationtimeout": + CommunicationTimeout = ExtractValue("communicationtimeout", () => + { throw new InvalidOperationException(string.Format("The communicationtimeout must be an integer: {0}", GetArgumentValue("communicationtimeout"))); }); + CommunicationTimeout = Math.Max(Math.Min(CommunicationTimeout, 60000), 10000); + break; case "filter": Filters = ExtractFilters(GetArgumentValue("filter")); break; @@ -511,6 +516,11 @@ private void ValidateArguments() /// Instructs the console to print its version and exit /// public bool PrintVersion { get; private set; } + + /// + /// Sets the 'short' timeout between profiler and host (normally 10000ms) + /// + public int CommunicationTimeout { get; private set; } } } \ No newline at end of file diff --git a/main/OpenCover.Test/Framework/CommandLineParserTests.cs b/main/OpenCover.Test/Framework/CommandLineParserTests.cs index 1f9deaf4a..ec07cffe9 100644 --- a/main/OpenCover.Test/Framework/CommandLineParserTests.cs +++ b/main/OpenCover.Test/Framework/CommandLineParserTests.cs @@ -719,6 +719,7 @@ public void HandlesServiceStartTimeout(string timeAsString, int expectedMinutes, Assert.That(parser.ServiceStartTimeout, Is.EqualTo(new TimeSpan(0, expectedMinutes, expectedSeconds))); } + [Test] [TestCase("10")] [TestCase("NaNs")] [TestCase("indifferenttext")] @@ -735,6 +736,41 @@ public void InvalidServiceStartTimeoutThrowsException(string invalidTimeout) Assert.That(thrownException.Message, Contains.Substring(invalidTimeout)); } + [Test] + [TestCase(10000, 10000)] + [TestCase(30000, 30000)] + [TestCase(60000, 60000)] + [TestCase(100, 10000)] + [TestCase(70000, 60000)] + public void HandlesCommunicationTimeout(int suppliedMillisconds, int expectedMiliseconds) + { + // arrange + var parser = new CommandLineParser(new[] { string.Format("-communicationtimeout:{0}", suppliedMillisconds), RequiredArgs }); + + // act + parser.ExtractAndValidateArguments(); + + // assert + Assert.That(parser.CommunicationTimeout, Is.EqualTo(expectedMiliseconds)); + + } + + [Test] + [TestCase("NaNs")] + [TestCase("indifferenttext")] + public void InvalidServiceCommunicationTimeoutThrowsException(string invalidTimeout) + { + // arrange + var parser = new CommandLineParser(new[] { "-communicationtimeout:" + invalidTimeout, RequiredArgs }); + + // act + var thrownException = Assert.Throws(parser.ExtractAndValidateArguments); + + // assert + Assert.That(thrownException.Message, Contains.Substring("communicationtimeout")); + Assert.That(thrownException.Message, Contains.Substring(invalidTimeout)); + } + [Test] [TestCase("-{nunit-console*}[*]* -{pdb*}[*]* -{nunit-agent*}[*]*")] [TestCase("-[System*]* -[Xyz*]* -[Zap*]*")] From 96385737c3ec9c16ca358688bbe52e16f7c58477 Mon Sep 17 00:00:00 2001 From: sawilde Date: Wed, 2 Dec 2015 07:56:24 +1100 Subject: [PATCH 12/41] update dogfood.cmd --- main/cmdline/dogfood.cmd | 1 + 1 file changed, 1 insertion(+) diff --git a/main/cmdline/dogfood.cmd b/main/cmdline/dogfood.cmd index 17ec381f5..3a618e264 100644 --- a/main/cmdline/dogfood.cmd +++ b/main/cmdline/dogfood.cmd @@ -1,3 +1,4 @@ +@echo off pushd %cd% cd %~dp0 OpenCover.Console.exe -register:user -target:..\..\..\main\packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -targetargs:"OpenCover.Test.dll /noshadow /exclude:AdminOnly" -filter:"+[Open*]* -[OpenCover.T*]* -{nunit-console*}[*]* -{pdb*}[*]*" -output:opencovertests.xml From fefb9eaf40f9a58686da315a4263e79ae5271002 Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 6 Dec 2015 15:32:28 +0100 Subject: [PATCH 13/41] Fix compile on VS 2013 Community Edition build create-release: OK --- main/OpenCover.UITest/LaunchSimpleTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main/OpenCover.UITest/LaunchSimpleTest.cs b/main/OpenCover.UITest/LaunchSimpleTest.cs index cc251a06f..cf168ec42 100644 --- a/main/OpenCover.UITest/LaunchSimpleTest.cs +++ b/main/OpenCover.UITest/LaunchSimpleTest.cs @@ -1,6 +1,6 @@ using System.Diagnostics; using System.IO; -using Microsoft.VisualStudio.TestTools.UITesting; +//using Microsoft.VisualStudio.TestTools.UITesting; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -9,7 +9,7 @@ namespace OpenCover.UITest /// /// Summary description for CodedUITest1 /// - [CodedUITest] + //[CodedUITest] public class LaunchSimpleTest { public LaunchSimpleTest() @@ -29,8 +29,8 @@ public void RunApp() pi.EnvironmentVariables["Stuff"] = "1"; pi.UseShellExecute = false; //pi.LoadUserProfile = true; - var application = ApplicationUnderTest.Launch(pi); - application.Process.WaitForExit(10000); + //var application = ApplicationUnderTest.Launch(pi); + //application.Process.WaitForExit(10000); } #region Additional test attributes From 31a11aa73e89d813e2b39dbe69cc283e88bb4c00 Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 6 Dec 2015 15:45:09 +0100 Subject: [PATCH 14/41] Change outputXml64 name build create-release: OK --- main/OpenCover.Specs/Steps/PackagingSteps.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/OpenCover.Specs/Steps/PackagingSteps.cs b/main/OpenCover.Specs/Steps/PackagingSteps.cs index e4358ef93..4fd432454 100644 --- a/main/OpenCover.Specs/Steps/PackagingSteps.cs +++ b/main/OpenCover.Specs/Steps/PackagingSteps.cs @@ -160,7 +160,7 @@ public void ThenTheCoverageResultsShouldBeTheSame() Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), "x86", Path.GetExtension(output)); var outputXml64 = string.Format(@"{0}\{1}_{2}.{3}", - Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), "x86", Path.GetExtension(output)); + Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), "x64", Path.GetExtension(output)); Assert.IsTrue(File.Exists(outputXml86)); Assert.IsTrue(File.Exists(outputXml64)); From ae32ac0e8cca27a784ddbc6f8653efaf620151eb Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 6 Dec 2015 17:24:48 +0100 Subject: [PATCH 15/41] Fix xml-result file double dot extension (..xml) build create-release: OK (now it works as intended) --- main/OpenCover.Specs/Steps/PackagingSteps.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/OpenCover.Specs/Steps/PackagingSteps.cs b/main/OpenCover.Specs/Steps/PackagingSteps.cs index 4fd432454..fca733f1b 100644 --- a/main/OpenCover.Specs/Steps/PackagingSteps.cs +++ b/main/OpenCover.Specs/Steps/PackagingSteps.cs @@ -132,7 +132,7 @@ public void WhenIExecuteTheDeployedOpenCoverAgainstTheXTargetApplicationInSubfol var folder = (string)ScenarioContext.Current["targetFolder"]; var output = (string)ScenarioContext.Current["targetOutput"]; - var outputXml = string.Format(@"{0}\{1}_{2}.{3}", + var outputXml = string.Format(@"{0}\{1}_{2}{3}", Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), binFolder, Path.GetExtension(output)); if (File.Exists(outputXml)) File.Delete(outputXml); @@ -156,10 +156,10 @@ public void ThenTheCoverageResultsShouldBeTheSame() var output = (string)ScenarioContext.Current["targetOutput"]; - var outputXml86 = string.Format(@"{0}\{1}_{2}.{3}", + var outputXml86 = string.Format(@"{0}\{1}_{2}{3}", Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), "x86", Path.GetExtension(output)); - var outputXml64 = string.Format(@"{0}\{1}_{2}.{3}", + var outputXml64 = string.Format(@"{0}\{1}_{2}{3}", Path.GetDirectoryName(output), Path.GetFileNameWithoutExtension(output), "x64", Path.GetExtension(output)); Assert.IsTrue(File.Exists(outputXml86)); From c920a075849142b73ded2c0341a2dc1a65bed500 Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 6 Dec 2015 17:49:45 +0100 Subject: [PATCH 16/41] If method has no sequences -> remove branches Fix expectet test result too build create-release: OK --- .../Persistance/BasePersistance.cs | 17 +++++++++++++---- .../Persistance/BasePersistenceTests.cs | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index d09e25b1b..2e2d8efa6 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -264,11 +264,20 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) foreach (var method in (@class.Methods ?? new Method[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) { - var sequencePoints = method.SequencePoints ?? new SequencePoint[0]; - var branchPoints = method.BranchPoints ?? new BranchPoint[0]; + if (method.SequencePoints == null) method.SequencePoints = new SequencePoint[0]; + if (method.BranchPoints == null) method.BranchPoints = new BranchPoint[0]; - MapFileReferences(sequencePoints, filesDictionary); - MapFileReferences(branchPoints, filesDictionary); + // use shorter names + var sequencePoints = method.SequencePoints; + var branchPoints = method.BranchPoints; + + // No sequences in method, but branches present? => remove branches + if (sequencePoints.Length == 0 && branchPoints.Length != 0) { + branchPoints = new BranchPoint[0]; + } + + if (sequencePoints.Length != 0) MapFileReferences(sequencePoints, filesDictionary); + if (branchPoints.Length != 0) MapFileReferences(branchPoints, filesDictionary); #region Merge branch-exits diff --git a/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs b/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs index f53dcb00d..ebeaf9d0a 100644 --- a/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs +++ b/main/OpenCover.Test/Framework/Persistance/BasePersistenceTests.cs @@ -340,8 +340,8 @@ public void Commit_With_WithBranchPointsOnly() Assert.AreEqual(0, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.NumSequencePoints); Assert.AreEqual(0, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.VisitedSequencePoints); - Assert.AreEqual(1, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.NumBranchPoints); - Assert.AreEqual(1, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.VisitedBranchPoints); + Assert.AreEqual(0, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.NumBranchPoints); + Assert.AreEqual(0, Instance.CoverageSession.Modules[0].Classes[0].Methods[0].Summary.VisitedBranchPoints); } [Test] From a07b4823682c268118fa457cb8eb627a7e53b118 Mon Sep 17 00:00:00 2001 From: ddur Date: Sun, 6 Dec 2015 20:22:59 +0100 Subject: [PATCH 17/41] Select only branches within sequence offset build create-release: OK --- .../Persistance/BasePersistance.cs | 114 +++++++++++------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 2e2d8efa6..8cfa310a1 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -230,8 +230,13 @@ private void RemoveUnreferencedFiles() } } + private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; + private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; + private static readonly List emptyBranchList = new List(0); + private void PopulateInstrumentedPoints() { + if (CoverageSession.Modules == null) return; foreach (var method in from @class in @@ -264,76 +269,92 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) foreach (var method in (@class.Methods ?? new Method[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) { - if (method.SequencePoints == null) method.SequencePoints = new SequencePoint[0]; - if (method.BranchPoints == null) method.BranchPoints = new BranchPoint[0]; + if (method.SequencePoints == null) method.SequencePoints = emptySeqPoints; + if (method.BranchPoints == null) method.BranchPoints = emptyBranchPoints; // use shorter names - var sequencePoints = method.SequencePoints; - var branchPoints = method.BranchPoints; + var sPoints = method.SequencePoints; + var bPoints = method.BranchPoints; // No sequences in method, but branches present? => remove branches - if (sequencePoints.Length == 0 && branchPoints.Length != 0) { - branchPoints = new BranchPoint[0]; + if (sPoints.Length == 0 && bPoints.Length != 0) { + bPoints = emptyBranchPoints; } - if (sequencePoints.Length != 0) MapFileReferences(sequencePoints, filesDictionary); - if (branchPoints.Length != 0) MapFileReferences(branchPoints, filesDictionary); + if (sPoints.Length != 0) MapFileReferences(sPoints, filesDictionary); + if (bPoints.Length != 0) MapFileReferences(bPoints, filesDictionary); #region Merge branch-exits + // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset + // ATTN: Sorted again to prevent future bugs if order of SP & BP is changed! + sPoints = sPoints.OrderBy( sp => sp.Offset ).ToArray(); + bPoints = bPoints.OrderBy( bp => bp.Offset ).ToArray(); + // anything to merge? - if (sequencePoints.Length != 0 && branchPoints.Length != 0) { + if (sPoints.Length != 0 && bPoints.Length != 0) { #region Join Sequences and Branches + // Quick match branches to sequence using SP&BP sort order by IL offset var index = 0; // get first sequencePoint and prepare list for Add(branchPoint) - var parent = sequencePoints[index]; - parent.BranchPoints = new List(); + var currentSp = sPoints[index]; + currentSp.BranchPoints = new List(); // get nextOffset - int nextOffset = index + 1 < sequencePoints.Length ? sequencePoints[index + 1].Offset : int.MaxValue; + int nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue; - foreach (var branchPoint in branchPoints) { + foreach (var currentBp in bPoints) { - // while branchPoint belongs to next sequencePoint - // nextOffset is offset of next sequencePoint - // or unreachable int.MinValue - while (branchPoint.Offset > nextOffset) { + /* + * As long as current_BP_offset is between + * current_SP_offset and [next_SP_offset], + * current_BP belongs to current_SP + */ + + // Is currentBp outside of scope of current_SP? + while (nextSpOffset != int.MinValue && currentBp.Offset >= nextSpOffset) { + + /* + * Find next sequence points pair where + * currentSp_offset <= currentBp_offset < nextSp_offset + */ // increment index to next sequencePoint ++index; // get next sequencePoint and prepare list for Add(branchPoint) - parent = sequencePoints[index]; - parent.BranchPoints = new List(); + currentSp = sPoints[index]; + currentSp.BranchPoints = new List(); - // get nextOffset - if (index + 1 < sequencePoints.Length) { - nextOffset = sequencePoints[index + 1].Offset; - } - else { - nextOffset = int.MaxValue; - } + // get nextSpOffset + nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue; + } + + // Add BranchPoint to curent SequencePoint + if (currentBp.Offset >= currentSp.Offset) { + currentSp.BranchPoints.Add(currentBp); } - // join BranchPoint to SequencePoint - parent.BranchPoints.Add(branchPoint); } #endregion - #region Merge each Sequence Branch-Exits + #region Merge Branch-Exits for each Sequence + + // Collection of validBranchPoints (child/connected to parent SequencePoint) + var validBranchPoints = new List(); var branchExits = new Dictionary(); - foreach (var sequencePoint in sequencePoints) { + foreach (var sp in sPoints) { // SequencePoint has branches attached? - if (sequencePoint.BranchPoints != null && sequencePoint.BranchPoints.Count != 0) { + if (sp.BranchPoints != null && sp.BranchPoints.Count != 0) { - // Merge SP.BranchPoints using EndOffset as branchExits key + // Merge sp.BranchPoints using EndOffset as branchExits key branchExits.Clear(); - foreach (var branchPoint in sequencePoint.BranchPoints) { + foreach (var branchPoint in sp.BranchPoints) { if (!branchExits.ContainsKey(branchPoint.EndOffset)) { branchExits[branchPoint.EndOffset] = branchPoint; // insert branch } else { @@ -342,16 +363,23 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) } // Update SequencePoint properties/attributes - sequencePoint.BranchExitsCount = 0; - sequencePoint.BranchExitsVisit = 0; + sp.BranchExitsCount = 0; + sp.BranchExitsVisit = 0; foreach (var branchPoint in branchExits.Values) { - sequencePoint.BranchExitsCount += 1; - sequencePoint.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; + sp.BranchExitsCount += 1; + sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; } + + // Add validBranchPoints + validBranchPoints.AddRange(sp.BranchPoints); + sp.BranchPoints = emptyBranchList; // clear } - sequencePoint.BranchPoints = null; // release memory } - + + // Replace original branchPoints with branches connected to sequence point(s) + bPoints = validBranchPoints.ToArray(); + validBranchPoints = emptyBranchList; // clear + #endregion } @@ -363,10 +391,10 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) method.Visited = (method.MethodPoint.VisitCount > 0); } - method.Summary.NumBranchPoints = branchPoints.Count(); - method.Summary.VisitedBranchPoints = branchPoints.Count(pt => pt.VisitCount != 0); - method.Summary.NumSequencePoints = sequencePoints.Count(); - method.Summary.VisitedSequencePoints = sequencePoints.Count(pt => pt.VisitCount != 0); + method.Summary.NumBranchPoints = bPoints.Count(); + method.Summary.VisitedBranchPoints = bPoints.Count(pt => pt.VisitCount != 0); + method.Summary.NumSequencePoints = sPoints.Count(); + method.Summary.VisitedSequencePoints = sPoints.Count(pt => pt.VisitCount != 0); if (method.Summary.NumSequencePoints > 0) method.Summary.NumBranchPoints += 1; From f7cd8ced8aa1829ecb41a44e7bac872d860aecd7 Mon Sep 17 00:00:00 2001 From: ddur Date: Mon, 7 Dec 2015 00:52:06 +0100 Subject: [PATCH 18/41] Exclude some compiler generated branches? build create-release: OK --- .../OpenCover.Framework/Persistance/BasePersistance.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 8cfa310a1..18f10bbc8 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -333,9 +333,13 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue; } - // Add BranchPoint to curent SequencePoint - if (currentBp.Offset >= currentSp.Offset) { - currentSp.BranchPoints.Add(currentBp); + // User (not by compiler) generated branches have line sequence longer than 2 characters? + // Rule above EXCLUDES branches within '{' & '}' & 'in' sequence points + if (currentSp.StartLine == currentSp.EndLine && (currentSp.EndColumn - currentSp.StartColumn) > 2) { + // Add BranchPoint to curent SequencePoint + if (currentBp.Offset >= currentSp.Offset) { + currentSp.BranchPoints.Add(currentBp); + } } } From 84efecc4eedcc3cec4555f833941045e4f157dea Mon Sep 17 00:00:00 2001 From: ddur Date: Mon, 7 Dec 2015 20:18:09 +0100 Subject: [PATCH 19/41] Revert "Exclude some compiler generated branches?" This reverts commit f7cd8ced8aa1829ecb41a44e7bac872d860aecd7. --- .../OpenCover.Framework/Persistance/BasePersistance.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 18f10bbc8..8cfa310a1 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -333,13 +333,9 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue; } - // User (not by compiler) generated branches have line sequence longer than 2 characters? - // Rule above EXCLUDES branches within '{' & '}' & 'in' sequence points - if (currentSp.StartLine == currentSp.EndLine && (currentSp.EndColumn - currentSp.StartColumn) > 2) { - // Add BranchPoint to curent SequencePoint - if (currentBp.Offset >= currentSp.Offset) { - currentSp.BranchPoints.Add(currentBp); - } + // Add BranchPoint to curent SequencePoint + if (currentBp.Offset >= currentSp.Offset) { + currentSp.BranchPoints.Add(currentBp); } } From c36eb67936702fc954b6bc26c2a625b095d73e63 Mon Sep 17 00:00:00 2001 From: sawilde Date: Tue, 8 Dec 2015 08:37:01 +1100 Subject: [PATCH 20/41] #335 pass connection timeout value through --- main/OpenCover.Framework/CommandLineParser.cs | 5 ++-- main/OpenCover.Framework/ICommandLine.cs | 5 ++++ .../Manager/ProfilerManager.cs | 5 +++- .../Framework/CommandLineParserTests.cs | 2 +- .../Framework/Manager/ProfilerManagerTests.cs | 27 +++++++++++++++++++ main/cmdline/dogfood.cmd | 2 +- 6 files changed, 41 insertions(+), 5 deletions(-) diff --git a/main/OpenCover.Framework/CommandLineParser.cs b/main/OpenCover.Framework/CommandLineParser.cs index 339cffc0a..5fc4d91fb 100644 --- a/main/OpenCover.Framework/CommandLineParser.cs +++ b/main/OpenCover.Framework/CommandLineParser.cs @@ -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:"); + builder.AppendLine(" [-communicationtimeout:"); builder.AppendLine(" [-threshold:]"); builder.AppendLine(" [-enableperformancecounters]"); builder.AppendLine(" [-skipautoprops]"); @@ -192,7 +193,7 @@ public void ExtractAndValidateArguments() break; case "communicationtimeout": CommunicationTimeout = ExtractValue("communicationtimeout", () => - { throw new InvalidOperationException(string.Format("The communicationtimeout must be an integer: {0}", GetArgumentValue("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": diff --git a/main/OpenCover.Framework/ICommandLine.cs b/main/OpenCover.Framework/ICommandLine.cs index 93a295475..eb697c417 100644 --- a/main/OpenCover.Framework/ICommandLine.cs +++ b/main/OpenCover.Framework/ICommandLine.cs @@ -53,5 +53,10 @@ public interface ICommandLine /// Should auto implemented properties be skipped /// bool SkipAutoImplementedProperties { get; } + + /// + /// Sets the 'short' timeout between profiler and host + /// + int CommunicationTimeout { get; } } } \ No newline at end of file diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index 106ea3113..b0045ee08 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -129,7 +129,10 @@ private void SetProfilerAttributesOnDictionary(string profilerKey, string profil dictionary["CoreClr_Enable_Profiling"] = "1"; dictionary["Cor_Profiler_Path"] = string.Empty; dictionary["CorClr_Profiler_Path"] = string.Empty; - + + if (_commandLine.CommunicationTimeout > 0) + dictionary["OpenCover_Profiler_ShortWait"] = _commandLine.CommunicationTimeout.ToString(); + switch (_commandLine.Registration) { case Registration.Path32: diff --git a/main/OpenCover.Test/Framework/CommandLineParserTests.cs b/main/OpenCover.Test/Framework/CommandLineParserTests.cs index ec07cffe9..bb0361fa1 100644 --- a/main/OpenCover.Test/Framework/CommandLineParserTests.cs +++ b/main/OpenCover.Test/Framework/CommandLineParserTests.cs @@ -767,7 +767,7 @@ public void InvalidServiceCommunicationTimeoutThrowsException(string invalidTime var thrownException = Assert.Throws(parser.ExtractAndValidateArguments); // assert - Assert.That(thrownException.Message, Contains.Substring("communicationtimeout")); + Assert.That(thrownException.Message, Contains.Substring("communication timeout")); Assert.That(thrownException.Message, Contains.Substring(invalidTimeout)); } diff --git a/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs b/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs index e7c593333..709ed20aa 100644 --- a/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs +++ b/main/OpenCover.Test/Framework/Manager/ProfilerManagerTests.cs @@ -77,6 +77,33 @@ public void Manager_Adds_Supplied_Threshold_EnvironmentVariable() Assert.NotNull(dict[@"OpenCover_Profiler_Threshold"]); Assert.AreEqual("500", dict[@"OpenCover_Profiler_Threshold"]); } + [Test] + public void Manager_DoesNotAdd_ShortWait_EnvironmentVariable() + { + // arrange + var dict = new StringDictionary(); + + // act + RunSimpleProcess(dict); + + // assert + Assert.Null(dict[@"OpenCover_Profiler_ShortWait"]); + } + + [Test] + public void Manager_Adds_Supplied_ShortWait_EnvironmentVariable() + { + // arrange + var dict = new StringDictionary(); + Container.GetMock().SetupGet(x => x.CommunicationTimeout).Returns(10000); + + // act + RunSimpleProcess(dict); + + // assert + Assert.NotNull(dict[@"OpenCover_Profiler_ShortWait"]); + Assert.AreEqual("10000", dict[@"OpenCover_Profiler_ShortWait"]); + } [Test] public void Manager_Adds_TraceByTest_EnvironmentVariable_When_Tracing_Enabled() diff --git a/main/cmdline/dogfood.cmd b/main/cmdline/dogfood.cmd index 3a618e264..d33e17758 100644 --- a/main/cmdline/dogfood.cmd +++ b/main/cmdline/dogfood.cmd @@ -1,5 +1,5 @@ @echo off pushd %cd% cd %~dp0 -OpenCover.Console.exe -register:user -target:..\..\..\main\packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -targetargs:"OpenCover.Test.dll /noshadow /exclude:AdminOnly" -filter:"+[Open*]* -[OpenCover.T*]* -{nunit-console*}[*]* -{pdb*}[*]*" -output:opencovertests.xml +OpenCover.Console.exe -register:user -target:..\..\..\main\packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -targetargs:"OpenCover.Test.dll /noshadow /exclude:AdminOnly" -filter:"+[Open*]* -[OpenCover.T*]* -{nunit-console*}[*]* -{pdb*}[*]*" -output:opencovertests.xml -communicationtimeout:9999 popd \ No newline at end of file From e60009d10768a34533a30d6f1dc65b4aad579589 Mon Sep 17 00:00:00 2001 From: ddur Date: Fri, 11 Dec 2015 13:37:26 +0100 Subject: [PATCH 21/41] Source connection --- .../Model/SequencePoint.cs | 8 +- .../OpenCover.Framework.csproj | 1 + .../Persistance/BasePersistance.cs | 61 ++++- .../Utility/CodeCoverageStringTextSource.cs | 254 ++++++++++++++++++ 4 files changed, 320 insertions(+), 4 deletions(-) create mode 100644 main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs diff --git a/main/OpenCover.Framework/Model/SequencePoint.cs b/main/OpenCover.Framework/Model/SequencePoint.cs index db19eb4a0..f0a556f17 100644 --- a/main/OpenCover.Framework/Model/SequencePoint.cs +++ b/main/OpenCover.Framework/Model/SequencePoint.cs @@ -37,10 +37,16 @@ public class SequencePoint : InstrumentationPoint, IDocumentReference /// [XmlAttribute("ec")] public int EndColumn { get; set; } - + + /// + /// Count of merged branches + /// [XmlAttribute("bec")] public int BranchExitsCount { get; set; } + /// + /// Visit count of merged branches + /// [XmlAttribute("bev")] public int BranchExitsVisit { get; set; } diff --git a/main/OpenCover.Framework/OpenCover.Framework.csproj b/main/OpenCover.Framework/OpenCover.Framework.csproj index cec4d7b0a..f001cdc48 100644 --- a/main/OpenCover.Framework/OpenCover.Framework.csproj +++ b/main/OpenCover.Framework/OpenCover.Framework.csproj @@ -145,6 +145,7 @@ + diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 8cfa310a1..39866052e 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -3,6 +3,7 @@ using System.Linq; using OpenCover.Framework.Communication; using OpenCover.Framework.Model; +using OpenCover.Framework.Utility; using log4net; namespace OpenCover.Framework.Persistance @@ -230,10 +231,44 @@ private void RemoveUnreferencedFiles() } } + // static readonly empty collections, saves creation time of new empty ones private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; private static readonly List emptyBranchList = new List(0); + // Dictionary with stored source files per module + private Dictionary sourceRepository = new Dictionary(); + + // Return if SequencePoint cannot have user defined branches + // So far have detected sequencePoints with branches on '{' '}' (static methods) + // and within keyword 'in'. My guess, VB 'In' is same as C# 'in' + private bool CanContainUserBranches ( SequencePoint sp ) { + if (sp.StartLine == sp.EndLine) { + string content = ""; + int spLength = sp.EndColumn - sp.StartColumn; + switch (spLength) { + case 1: + case 2: + if (sp.FileId != 0) { + CodeCoverageStringTextSource source = null; + sourceRepository.TryGetValue(sp.FileId, out source); + if (source != null) { + content = source.GetText(sp); + } + } + break; + } + switch (content) { + case "{": //C# + case "}": //C# + case "in": //C# + case "In": //VB + return false; + } + } + return true; + } + private void PopulateInstrumentedPoints() { @@ -256,15 +291,25 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #region Module File/FileID Dictionary + sourceRepository = new Dictionary(); var filesDictionary = new Dictionary(); - foreach (var file in (module.Files ?? new File[0]).Where(file => !filesDictionary.ContainsKey(file.FullPath ?? ""))) + foreach (var file in (module.Files ?? new File[0]).Where(file => !String.IsNullOrWhiteSpace(file.FullPath) && !filesDictionary.ContainsKey(file.FullPath))) { - filesDictionary.Add(file.FullPath ?? "", file.UniqueId); + var source = CodeCoverageStringTextSource.GetSource(file.FullPath); + if (source != null) sourceRepository.Add (file.UniqueId, source); + filesDictionary.Add(file.FullPath, file.UniqueId); } #endregion - foreach (var @class in (module.Classes ?? new Class[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) + #region TODO:? Merge Compiler Extracted/Generated Methods (enumerator methods) + + // Store repeated Query + var classesQuery = (module.Classes ?? new Class[0]).Where(x => !x.ShouldSerializeSkippedDueTo()); + + #endregion + + foreach (var @class in classesQuery) { foreach (var method in (@class.Methods ?? new Method[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) @@ -339,6 +384,16 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) } } + #endregion + + #region Remove Compiler Generated Branches + + foreach (var sp in sPoints) { + if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && !CanContainUserBranches(sp)) { + sp.BranchPoints = emptyBranchList; + } + } + #endregion #region Merge Branch-Exits for each Sequence diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs new file mode 100644 index 000000000..c09406ce0 --- /dev/null +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -0,0 +1,254 @@ +// Copyright (c) https://github.com/ddur +// This code is distributed under MIT license + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using OpenCover.Framework.Model; + +namespace OpenCover.Framework.Utility +{ + /// StringTextSource (ReadOnly) + /// Line and column counting starts at 1. + /// IDocument/ITextBuffer/ITextSource fails returning single char "{"? + /// + public class CodeCoverageStringTextSource + { + private readonly string textSource; + private struct lineInfo { + public int Offset; + public int Length; + } + private readonly lineInfo[] lines; + /// + /// Constructor + /// + /// + public CodeCoverageStringTextSource(string source) + { + this.textSource = source; + + lineInfo line; + var lineInfoList = new List(); + int offset = 0; + int counter = 0; + bool newLine = false; + bool cr = false; + bool lf = false; + + foreach ( ushort ch in textSource ) { + switch (ch) { + case 0xD: + if (lf||cr) { + newLine = true; // cr after cr|lf + } else { + cr = true; // cr found + } + break; + case 0xA: + if (lf) { + newLine = true; // lf after lf + } else { + lf = true; // lf found + } + break; + default: + if (cr||lf) { + newLine = true; // any non-line-end char after any line-end + } + break; + } + if (newLine) { // newLine detected - add line + line = new lineInfo(); + line.Offset = offset; + line.Length = counter - offset; + lineInfoList.Add(line); + offset = counter; + cr = false; + lf = false; + newLine = false; + } + ++counter; + } + + // Add last line + line = new lineInfo(); + line.Offset = offset; + line.Length = counter - offset; + lineInfoList.Add(line); + + // Store to readonly field + lines = lineInfoList.ToArray(); + } + + /// Return text/source using SequencePoint line/col info + /// + /// + /// + public string GetText(SequencePoint sp) { + return this.GetText(sp.StartLine, sp.StartColumn, sp.EndLine, sp.EndColumn ); + } + + /// Return text at Line/Column/EndLine/EndColumn position + /// Line and Column counting starts at 1. + /// + /// + /// + /// + /// + /// + public string GetText(int Line, int Column, int EndLine, int EndColumn) { + + var text = new StringBuilder(); + string line; + bool argOutOfRange; + + if (Line==EndLine) { + + #region One-Line request + line = GetLine(Line); + + //Debug.Assert(!(Column < 1), "Column < 1"); + //Debug.Assert(!(Column > EndColumn), "Column > EndColumn"); + //Debug.Assert(!(EndColumn > line.Length + 1), string.Format ("Single Line EndColumn({0}) > line.Length({1})",EndColumn, line.Length )); + //Debug.Assert(!(EndColumn > line.Length + 1), line); + + argOutOfRange = Column < 1 + || Column > EndColumn + || EndColumn > line.Length; + if (!argOutOfRange) { + text.Append(line.Substring(Column-1,EndColumn-Column)); + } + #endregion + + } else if (Line line.Length), string.Format ("First MultiLine EndColumn({0}) > line.Length({1})",EndColumn, line.Length )); + + argOutOfRange = Column < 1 + || Column > line.Length; + if (!argOutOfRange) { + text.Append(line.Substring(Column-1)); + } + #endregion + + #region More than two lines + for ( int lineIndex = Line+1; lineIndex < EndLine; lineIndex++ ) { + text.Append ( GetLine ( lineIndex ) ); + } + #endregion + + #region Last line + line = GetLine(EndLine); + + //Debug.Assert(!(EndColumn < 1), "EndColumn < 1"); + //Debug.Assert(!(EndColumn > line.Length), string.Format ("Last MultiLine EndColumn({0}) > line.Length({1})",EndColumn, line.Length )); + + argOutOfRange = EndColumn < 1 + || EndColumn > line.Length; + if (!argOutOfRange) { + text.Append(line.Substring(0,EndColumn)); + } + #endregion + + #endregion + + } else { + //Debug.Fail("Line > EndLine"); + } + return text.ToString(); + } + + /// + /// Return number of lines in source + /// + public int LinesCount { + get { + return lines.Length; + } + } + + /// Return SequencePoint enumerated line + /// + /// + /// + public string GetLine ( int LineNo ) { + + string retString = String.Empty; + + if ( LineNo > 0 && LineNo <= lines.Length ) { + lineInfo lineInfo = lines[LineNo-1]; + retString = textSource.Substring(lineInfo.Offset, lineInfo.Length); + } else { + //Debug.Fail( "Line number out of range" ); + } + + return retString; + } + + /// + /// + /// + /// + /// + /// + public static string IndentTabs ( string ToIndent, int TabSize ) { + + string retString = ToIndent; + if ( ToIndent.Contains ( "\t" ) ) { + int counter = 0; + int remains = 0; + int repeat = 0; + char prevChar = char.MinValue; + var indented = new StringBuilder(); + foreach ( char currChar in ToIndent ) { + if ( currChar == '\t' ) { + remains = counter % TabSize; + repeat = remains == 0 ? TabSize : remains; + indented.Append( ' ', repeat ); + } else { + indented.Append ( currChar, 1 ); + if ( char.IsLowSurrogate(currChar) + && char.IsHighSurrogate(prevChar) + ) { --counter; } + } + prevChar = currChar; + ++counter; + } + retString = indented.ToString(); + } + return retString; + } + + /// + /// Get line-parsed source from file name + /// + /// + /// + public static CodeCoverageStringTextSource GetSource(string filename) { + + var retSource = (CodeCoverageStringTextSource)null; + try { + using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { + try { + stream.Position = 0; + using (var reader = new StreamReader (stream, Encoding.Default, true)) { + retSource = new CodeCoverageStringTextSource(reader.ReadToEnd()); + } + } catch (Exception) {} + } + } catch (Exception) {} + + return retSource; + } + + } +} From 939d8d1818b67339140605d2711f05de431cd14d Mon Sep 17 00:00:00 2001 From: ddur Date: Tue, 15 Dec 2015 00:20:32 +0100 Subject: [PATCH 22/41] Add CrashReporter to zip distribution --- build/installer.build | 1 + 1 file changed, 1 insertion(+) diff --git a/build/installer.build b/build/installer.build index b67a6a7f1..9ed75bcc2 100644 --- a/build/installer.build +++ b/build/installer.build @@ -21,6 +21,7 @@ + From e274d401d93cc1da52280c3c12ff85257686ec48 Mon Sep 17 00:00:00 2001 From: ddur Date: Tue, 15 Dec 2015 00:21:09 +0100 Subject: [PATCH 23/41] Add Signed CrashReporter --- .../CrashReporterSigned/CrashReporter.NET.dll | Bin 0 -> 109056 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/CrashReporterSigned/CrashReporter.NET.dll diff --git a/tools/CrashReporterSigned/CrashReporter.NET.dll b/tools/CrashReporterSigned/CrashReporter.NET.dll new file mode 100644 index 0000000000000000000000000000000000000000..f2d05ec7ac96b4ad498e8edd3214379a08bb61ec GIT binary patch literal 109056 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 Date: Tue, 15 Dec 2015 14:44:29 +0100 Subject: [PATCH 24/41] Regex Filter Valid Branch Points Filter SequencePoints containing user-code branches, instead of removing recognized compiler generated branches --- .../Persistance/BasePersistance.cs | 127 ++++++++++++++---- .../Utility/CodeCoverageStringTextSource.cs | 35 ++++- 2 files changed, 132 insertions(+), 30 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 39866052e..a7accbbd4 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using OpenCover.Framework.Communication; using OpenCover.Framework.Model; using OpenCover.Framework.Utility; @@ -239,36 +240,104 @@ private void RemoveUnreferencedFiles() // Dictionary with stored source files per module private Dictionary sourceRepository = new Dictionary(); - // Return if SequencePoint cannot have user defined branches - // So far have detected sequencePoints with branches on '{' '}' (static methods) - // and within keyword 'in'. My guess, VB 'In' is same as C# 'in' - private bool CanContainUserBranches ( SequencePoint sp ) { - if (sp.StartLine == sp.EndLine) { - string content = ""; - int spLength = sp.EndColumn - sp.StartColumn; - switch (spLength) { - case 1: - case 2: - if (sp.FileId != 0) { - CodeCoverageStringTextSource source = null; - sourceRepository.TryGetValue(sp.FileId, out source); - if (source != null) { - content = source.GetText(sp); - } - } - break; - } - switch (content) { - case "{": //C# - case "}": //C# - case "in": //C# - case "In": //VB - return false; - } - } - return true; + private static Regex ifMatch = new Regex (@"\Aif\s*\(", RegexOptions.Compiled); + private static Regex switchMatch = new Regex (@"\Aswitch\s*\(", RegexOptions.Compiled); + private static Regex whileMatch = new Regex (@"\Awhile\s*\(", RegexOptions.Compiled); + private static Regex forMatch = new Regex (@"\Afor\s*\(", RegexOptions.Compiled); + private static Regex foreachMatch = new Regex (@"\Aforeach\s*\(", RegexOptions.Compiled); + private static Regex tryMatch = new Regex (@"\Atry\s*\{", RegexOptions.Compiled); + + private static Regex assignBoolMatch = new Regex (@"(?])=(?!\s*[=><]).+(\|\s*\||&\s*&|=\s*=|!\s*=|>\s*=|<\s*=|\?\s*\?|\?|:|<|>|\|).*;", RegexOptions.Compiled); + private static Regex evalBoolMatch = new Regex (@"\(.*(\|\s*\||&\s*&|=\s*=|!\s*=|>\s*=|<\s*=|\?\s*\?|\?|:|<|>|\|).*\)\s*;", RegexOptions.Compiled); + + private static Regex cRequiresMatch = new Regex (@"Contract\s*\.\s*Requires", RegexOptions.Compiled); + private static Regex cInvariantMatch = new Regex (@"Contract\s*\.\s*Invariant", RegexOptions.Compiled); + private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*Ensures", RegexOptions.Compiled); + + private const bool doRemove = true; + private const bool preserve = false; + + // Return true if branches can be removed + private bool doRemoveBranches (SequencePoint sp) { + if (sp == null) + return preserve; + if (sp.FileId == 0) + return preserve; + + CodeCoverageStringTextSource source = null; + sourceRepository.TryGetValue (sp.FileId, out source); + if (source == null) + return preserve; + + switch (source.FileType) { + case FileType.Unsupported: + return preserve; + + case FileType.CSharp: + break; // continue + case FileType.VBasic: + return preserve; + + default: +#if DEBUG + throw new NotImplementedException ("Source.FileType"); +#else + return preserve; +#endif + } + + string spSource = source.GetText (sp); + if (String.IsNullOrWhiteSpace (spSource)) + return preserve; + if (spSource.Length < 5) + return doRemove; //if(x); x=a|b; + + switch (spSource.Substring (0, 2)) { + case "if": // if ( + if (ifMatch.IsMatch (spSource)) + return preserve; + break; + + case "sw": // switch ( + if (switchMatch.IsMatch (spSource)) + return preserve; + break; + + case "wh": // while ( + if (whileMatch.IsMatch (spSource)) + return preserve; + break; + + case "fo": // for|foreach ( + if (forMatch.IsMatch (spSource)) + return preserve; + if (foreachMatch.IsMatch (spSource)) + return preserve; + break; + + case "tr": // try { + if (tryMatch.IsMatch (spSource)) + return preserve; + break; + + case "Co": // Contract.* + if (cRequiresMatch.IsMatch (spSource)) + return preserve; + if (cInvariantMatch.IsMatch (spSource)) + return doRemove; + if (cEnsuresMatch.IsMatch (spSource)) + return doRemove; + break; + + default: + break; + } + if (BasePersistance.assignBoolMatch.IsMatch (spSource) || BasePersistance.evalBoolMatch.IsMatch (spSource)) + return preserve; + return doRemove; } + private void PopulateInstrumentedPoints() { @@ -389,7 +458,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #region Remove Compiler Generated Branches foreach (var sp in sPoints) { - if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && !CanContainUserBranches(sp)) { + if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && doRemoveBranches(sp)) { sp.BranchPoints = emptyBranchList; } } diff --git a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs index c09406ce0..df8e5e6e1 100644 --- a/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs +++ b/main/OpenCover.Framework/Utility/CodeCoverageStringTextSource.cs @@ -10,12 +10,34 @@ namespace OpenCover.Framework.Utility { + /// + /// FileType enum + /// + public enum FileType : byte { + /// + /// Unsupported file extension + /// + Unsupported, + + /// + /// File extension is ".cs" + /// + CSharp, + + /// + /// File extension is ".vb" + /// + VBasic + } /// StringTextSource (ReadOnly) /// Line and column counting starts at 1. - /// IDocument/ITextBuffer/ITextSource fails returning single char "{"? /// public class CodeCoverageStringTextSource { + /// + /// File Type by file name extension + /// + public FileType FileType = FileType.Unsupported; private readonly string textSource; private struct lineInfo { public int Offset; @@ -242,6 +264,17 @@ public static CodeCoverageStringTextSource GetSource(string filename) { stream.Position = 0; using (var reader = new StreamReader (stream, Encoding.Default, true)) { retSource = new CodeCoverageStringTextSource(reader.ReadToEnd()); + switch (Path.GetExtension(filename).ToLowerInvariant()) { + case ".cs": + retSource.FileType = FileType.CSharp; + break; + case ".vb": + retSource.FileType = FileType.VBasic; + break; + default: + retSource.FileType = FileType.Unsupported; + break; + } } } catch (Exception) {} } From 757e9ea1f9a8d4458062d9a0bf6143f2a9e8fc02 Mon Sep 17 00:00:00 2001 From: ddur Date: Tue, 15 Dec 2015 16:51:21 +0100 Subject: [PATCH 25/41] More regex matches --- .../Persistance/BasePersistance.cs | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index a7accbbd4..7932253dc 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -240,19 +240,32 @@ private void RemoveUnreferencedFiles() // Dictionary with stored source files per module private Dictionary sourceRepository = new Dictionary(); + // match if ( private static Regex ifMatch = new Regex (@"\Aif\s*\(", RegexOptions.Compiled); + // match else if ( + private static Regex elseifMatch = new Regex (@"\Aelse\s+if\s*\(", RegexOptions.Compiled); + // match switch ( private static Regex switchMatch = new Regex (@"\Aswitch\s*\(", RegexOptions.Compiled); + // match while ( private static Regex whileMatch = new Regex (@"\Awhile\s*\(", RegexOptions.Compiled); + // match for ( private static Regex forMatch = new Regex (@"\Afor\s*\(", RegexOptions.Compiled); + // match foreach ( private static Regex foreachMatch = new Regex (@"\Aforeach\s*\(", RegexOptions.Compiled); + // match try { private static Regex tryMatch = new Regex (@"\Atry\s*\{", RegexOptions.Compiled); + // match anything like "= boolean expression" private static Regex assignBoolMatch = new Regex (@"(?])=(?!\s*[=><]).+(\|\s*\||&\s*&|=\s*=|!\s*=|>\s*=|<\s*=|\?\s*\?|\?|:|<|>|\|).*;", RegexOptions.Compiled); + // match anything like (boolean expression) private static Regex evalBoolMatch = new Regex (@"\(.*(\|\s*\||&\s*&|=\s*=|!\s*=|>\s*=|<\s*=|\?\s*\?|\?|:|<|>|\|).*\)\s*;", RegexOptions.Compiled); - private static Regex cRequiresMatch = new Regex (@"Contract\s*\.\s*Requires", RegexOptions.Compiled); - private static Regex cInvariantMatch = new Regex (@"Contract\s*\.\s*Invariant", RegexOptions.Compiled); - private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*Ensures", RegexOptions.Compiled); + // match Contract.Requires<*> ( + private static Regex cRequiresMatch = new Regex (@"Contract\s*\.\s*Requires\s*<.*>\s*\(", RegexOptions.Compiled); + // match Contract.Invariant ( + private static Regex cInvariantMatch = new Regex (@"Contract\s*\.\s*Invariant\s*\(", RegexOptions.Compiled); + // match Contract.Ensures[OnThrow<*>] ( + private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*(Ensures|EnsuresOnThrow\s*<.*>)\s*\(", RegexOptions.Compiled); private const bool doRemove = true; private const bool preserve = false; @@ -263,6 +276,8 @@ private bool doRemoveBranches (SequencePoint sp) { return preserve; if (sp.FileId == 0) return preserve; + if (sp.StartLine == sp.EndLine && (sp.EndColumn - sp.StartColumn) <= 2) + return doRemove; CodeCoverageStringTextSource source = null; sourceRepository.TryGetValue (sp.FileId, out source); @@ -280,7 +295,7 @@ private bool doRemoveBranches (SequencePoint sp) { default: #if DEBUG - throw new NotImplementedException ("Source.FileType"); + throw new NotImplementedException ("Source.FileType"); #else return preserve; #endif @@ -288,9 +303,9 @@ private bool doRemoveBranches (SequencePoint sp) { string spSource = source.GetText (sp); if (String.IsNullOrWhiteSpace (spSource)) - return preserve; + return doRemove; if (spSource.Length < 5) - return doRemove; //if(x); x=a|b; + return doRemove; // { } in (if(x) x=a|b) switch (spSource.Substring (0, 2)) { case "if": // if ( @@ -298,6 +313,11 @@ private bool doRemoveBranches (SequencePoint sp) { return preserve; break; + case "el": // else if ( + if (elseifMatch.IsMatch (spSource)) + return preserve; + break; + case "sw": // switch ( if (switchMatch.IsMatch (spSource)) return preserve; @@ -321,12 +341,14 @@ private bool doRemoveBranches (SequencePoint sp) { break; case "Co": // Contract.* - if (cRequiresMatch.IsMatch (spSource)) - return preserve; - if (cInvariantMatch.IsMatch (spSource)) - return doRemove; - if (cEnsuresMatch.IsMatch (spSource)) - return doRemove; + if (spSource.Length > 8 && spSource.Substring(0, 8) == "Contract") { + if (cRequiresMatch.IsMatch (spSource)) + return preserve; + if (cInvariantMatch.IsMatch (spSource)) + return doRemove; + if (cEnsuresMatch.IsMatch (spSource)) + return doRemove; + } break; default: From 73e73256ad0e08d33e8271d178fc9748021221e3 Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Wed, 16 Dec 2015 07:52:45 +1100 Subject: [PATCH 26/41] #376 only lock on buffer allocation if failed initially (performance) --- ReleaseNotes.tmp | 3 +++ .../OpenCover.Profiler/ProfilerCommunication.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ReleaseNotes.tmp b/ReleaseNotes.tmp index b32197fc1..6feff20b1 100644 --- a/ReleaseNotes.tmp +++ b/ReleaseNotes.tmp @@ -1,4 +1,7 @@ Version [[version]] +#376 protect buffer allocation in multithreaded environment (fix) + +Version 4.6.210 #282 exclude by process (feature) #246 auto crash reports (feature) #329 address ArgumentOutOfRangeException (potentially related to #274) (fix for VS2015) diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp index 2f62a17ef..37ee0e45f 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.cpp +++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp @@ -209,15 +209,15 @@ MSG_SendVisitPoints_Request* ProfilerCommunication::AllocateVisitMap(DWORD osThr MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG osThreadID){ MSG_SendVisitPoints_Request * p; - try { - p = m_visitmap[osThreadID]; - if (p == nullptr) - p = AllocateVisitMap(osThreadID); - } - catch (...){ - p = AllocateVisitMap(osThreadID); + auto it = m_visitmap.find(osThreadID); + if (it == m_visitmap.end()) { + ATL::CComCritSecLock lock(m_critThreads); + it = m_visitmap.find(osThreadID); + if (it == m_visitmap.end()) { + return AllocateVisitMap(osThreadID); + } } - return p; + return it->second; } void ProfilerCommunication::ThreadDestroyed(ThreadID threadID){ From 62cbb49973c6c9885d2640152af275b65aeb3bc9 Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Wed, 16 Dec 2015 08:03:07 +1100 Subject: [PATCH 27/41] #246 add missing assemblies --- build/installer.build | 1 + main/OpenCover.NugetPackage/OpenCover.nuspec | 1 + 2 files changed, 2 insertions(+) diff --git a/build/installer.build b/build/installer.build index b67a6a7f1..9ed75bcc2 100644 --- a/build/installer.build +++ b/build/installer.build @@ -21,6 +21,7 @@ + diff --git a/main/OpenCover.NugetPackage/OpenCover.nuspec b/main/OpenCover.NugetPackage/OpenCover.nuspec index 0cd4571a6..8ef771177 100644 --- a/main/OpenCover.NugetPackage/OpenCover.nuspec +++ b/main/OpenCover.NugetPackage/OpenCover.nuspec @@ -36,6 +36,7 @@ + From 4ec44f8a076208e0c04f8e400b0b31921babdc9a Mon Sep 17 00:00:00 2001 From: Shaun Wilde Date: Wed, 16 Dec 2015 08:10:29 +1100 Subject: [PATCH 28/41] update temp --- ReleaseNotes.tmp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseNotes.tmp b/ReleaseNotes.tmp index 6feff20b1..f4a23025f 100644 --- a/ReleaseNotes.tmp +++ b/ReleaseNotes.tmp @@ -1,7 +1,7 @@ Version [[version]] #376 protect buffer allocation in multithreaded environment (fix) -Version 4.6.210 +Version 4.6.210 (rc - remove) #282 exclude by process (feature) #246 auto crash reports (feature) #329 address ArgumentOutOfRangeException (potentially related to #274) (fix for VS2015) From 9db3624b337f2ca8cd1495692607d74553e0345e Mon Sep 17 00:00:00 2001 From: ddur Date: Wed, 16 Dec 2015 03:13:31 +0100 Subject: [PATCH 29/41] Cannot match include BranchPoint's at unexpected places, back to match exclude --- .../Persistance/BasePersistance.cs | 209 +++++------------- 1 file changed, 60 insertions(+), 149 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 7932253dc..bf18d2a87 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -233,51 +233,32 @@ private void RemoveUnreferencedFiles() } // static readonly empty collections, saves creation time of new empty ones - private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; + private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; private static readonly List emptyBranchList = new List(0); // Dictionary with stored source files per module private Dictionary sourceRepository = new Dictionary(); - // match if ( - private static Regex ifMatch = new Regex (@"\Aif\s*\(", RegexOptions.Compiled); - // match else if ( - private static Regex elseifMatch = new Regex (@"\Aelse\s+if\s*\(", RegexOptions.Compiled); - // match switch ( - private static Regex switchMatch = new Regex (@"\Aswitch\s*\(", RegexOptions.Compiled); - // match while ( - private static Regex whileMatch = new Regex (@"\Awhile\s*\(", RegexOptions.Compiled); - // match for ( - private static Regex forMatch = new Regex (@"\Afor\s*\(", RegexOptions.Compiled); - // match foreach ( - private static Regex foreachMatch = new Regex (@"\Aforeach\s*\(", RegexOptions.Compiled); - // match try { - private static Regex tryMatch = new Regex (@"\Atry\s*\{", RegexOptions.Compiled); - - // match anything like "= boolean expression" - private static Regex assignBoolMatch = new Regex (@"(?])=(?!\s*[=><]).+(\|\s*\||&\s*&|=\s*=|!\s*=|>\s*=|<\s*=|\?\s*\?|\?|:|<|>|\|).*;", RegexOptions.Compiled); - // match anything like (boolean expression) - private static Regex evalBoolMatch = new Regex (@"\(.*(\|\s*\||&\s*&|=\s*=|!\s*=|>\s*=|<\s*=|\?\s*\?|\?|:|<|>|\|).*\)\s*;", RegexOptions.Compiled); - // match Contract.Requires<*> ( - private static Regex cRequiresMatch = new Regex (@"Contract\s*\.\s*Requires\s*<.*>\s*\(", RegexOptions.Compiled); + private static Regex cRequiresMatch = new Regex (@"Contract\s*\.\s*Requires\s*<.+>\s*\(", RegexOptions.Compiled); // match Contract.Invariant ( private static Regex cInvariantMatch = new Regex (@"Contract\s*\.\s*Invariant\s*\(", RegexOptions.Compiled); // match Contract.Ensures[OnThrow<*>] ( - private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*(Ensures|EnsuresOnThrow\s*<.*>)\s*\(", RegexOptions.Compiled); + private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*(Ensures|EnsuresOnThrow\s*<.+>)\s*\(", RegexOptions.Compiled); private const bool doRemove = true; private const bool preserve = false; + //private static readonly ILog Logger = LogManager.GetLogger("OpenCover"); + // Return true if branches can be removed private bool doRemoveBranches (SequencePoint sp) { + if (sp == null) return preserve; if (sp.FileId == 0) return preserve; - if (sp.StartLine == sp.EndLine && (sp.EndColumn - sp.StartColumn) <= 2) - return doRemove; CodeCoverageStringTextSource source = null; sourceRepository.TryGetValue (sp.FileId, out source); @@ -287,76 +268,44 @@ private bool doRemoveBranches (SequencePoint sp) { switch (source.FileType) { case FileType.Unsupported: return preserve; - case FileType.CSharp: break; // continue case FileType.VBasic: return preserve; - default: #if DEBUG - throw new NotImplementedException ("Source.FileType"); + throw new NotImplementedException ("Source.FileType"); #else - return preserve; + return preserve; #endif } string spSource = source.GetText (sp); if (String.IsNullOrWhiteSpace (spSource)) return doRemove; - if (spSource.Length < 5) - return doRemove; // { } in (if(x) x=a|b) - - switch (spSource.Substring (0, 2)) { - case "if": // if ( - if (ifMatch.IsMatch (spSource)) - return preserve; - break; - case "el": // else if ( - if (elseifMatch.IsMatch (spSource)) - return preserve; + switch (spSource.Length) { + case 1: + if (spSource == "{" || spSource == "}") return doRemove; break; - - case "sw": // switch ( - if (switchMatch.IsMatch (spSource)) - return preserve; - break; - - case "wh": // while ( - if (whileMatch.IsMatch (spSource)) - return preserve; - break; - - case "fo": // for|foreach ( - if (forMatch.IsMatch (spSource)) - return preserve; - if (foreachMatch.IsMatch (spSource)) - return preserve; - break; - - case "tr": // try { - if (tryMatch.IsMatch (spSource)) - return preserve; - break; - - case "Co": // Contract.* - if (spSource.Length > 8 && spSource.Substring(0, 8) == "Contract") { - if (cRequiresMatch.IsMatch (spSource)) - return preserve; - if (cInvariantMatch.IsMatch (spSource)) - return doRemove; - if (cEnsuresMatch.IsMatch (spSource)) - return doRemove; - } - break; - default: + // contract. + // requires(x); + // invariant(x); + // ensures(x); + // ensuresOnThrow(x); + // 12345678901234567890 + if (spSource.Length >= 20 && spSource.Substring(0, 8) == "Contract" && spSource.Last() == ';') { +// if (cRequiresMatch.IsMatch (spSource)) +// return doRemove; + if (cInvariantMatch.IsMatch (spSource)) + return doRemove; + if (cEnsuresMatch.IsMatch (spSource)) + return doRemove; + } break; } - if (BasePersistance.assignBoolMatch.IsMatch (spSource) || BasePersistance.evalBoolMatch.IsMatch (spSource)) - return preserve; - return doRemove; + return preserve; } @@ -386,8 +335,8 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) var filesDictionary = new Dictionary(); foreach (var file in (module.Files ?? new File[0]).Where(file => !String.IsNullOrWhiteSpace(file.FullPath) && !filesDictionary.ContainsKey(file.FullPath))) { - var source = CodeCoverageStringTextSource.GetSource(file.FullPath); - if (source != null) sourceRepository.Add (file.UniqueId, source); + var source = CodeCoverageStringTextSource.GetSource(file.FullPath); + if (source != null) sourceRepository.Add (file.UniqueId, source); filesDictionary.Add(file.FullPath, file.UniqueId); } @@ -408,81 +357,43 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) if (method.SequencePoints == null) method.SequencePoints = emptySeqPoints; if (method.BranchPoints == null) method.BranchPoints = emptyBranchPoints; - // use shorter names - var sPoints = method.SequencePoints; - var bPoints = method.BranchPoints; - // No sequences in method, but branches present? => remove branches - if (sPoints.Length == 0 && bPoints.Length != 0) { - bPoints = emptyBranchPoints; + if (method.SequencePoints.Length == 0 && method.BranchPoints.Length != 0) { + method.BranchPoints = emptyBranchPoints; } - if (sPoints.Length != 0) MapFileReferences(sPoints, filesDictionary); - if (bPoints.Length != 0) MapFileReferences(bPoints, filesDictionary); + if (method.SequencePoints.Length != 0) MapFileReferences(method.SequencePoints, filesDictionary); + if (method.BranchPoints.Length != 0) MapFileReferences(method.BranchPoints, filesDictionary); #region Merge branch-exits - // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset - // ATTN: Sorted again to prevent future bugs if order of SP & BP is changed! - sPoints = sPoints.OrderBy( sp => sp.Offset ).ToArray(); - bPoints = bPoints.OrderBy( bp => bp.Offset ).ToArray(); - - // anything to merge? - if (sPoints.Length != 0 && bPoints.Length != 0) { + // anything to join, filter, merge? + if (method.SequencePoints.Length != 0 && method.BranchPoints.Length != 0) { #region Join Sequences and Branches // Quick match branches to sequence using SP&BP sort order by IL offset - var index = 0; - - // get first sequencePoint and prepare list for Add(branchPoint) - var currentSp = sPoints[index]; - currentSp.BranchPoints = new List(); - - // get nextOffset - int nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue; - - foreach (var currentBp in bPoints) { - - /* - * As long as current_BP_offset is between - * current_SP_offset and [next_SP_offset], - * current_BP belongs to current_SP - */ - - // Is currentBp outside of scope of current_SP? - while (nextSpOffset != int.MinValue && currentBp.Offset >= nextSpOffset) { - - /* - * Find next sequence points pair where - * currentSp_offset <= currentBp_offset < nextSp_offset - */ - - // increment index to next sequencePoint - ++index; - - // get next sequencePoint and prepare list for Add(branchPoint) - currentSp = sPoints[index]; - currentSp.BranchPoints = new List(); - - // get nextSpOffset - nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue; - } - - // Add BranchPoint to curent SequencePoint - if (currentBp.Offset >= currentSp.Offset) { - currentSp.BranchPoints.Add(currentBp); + // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset + // ATTN: Sorted again to prevent future bugs if order of SP & BP is changed! + method.SequencePoints = method.SequencePoints.OrderBy( sp => sp.Offset ).ToArray(); + method.BranchPoints = method.BranchPoints.OrderBy( bp => bp.Offset ).ToArray(); + + var branchStack = new Stack(method.BranchPoints); // Stack.Pop is constant time + foreach (SequencePoint sPoint in method.SequencePoints.Reverse()) { + sPoint.BranchPoints = new List(); + while (branchStack.Count != 0 && branchStack.Peek().Offset >= sPoint.Offset) { + sPoint.BranchPoints.Add(branchStack.Pop()); } } - + #endregion - #region Remove Compiler Generated Branches + #region Remove Compiler Generated Branches from SequencePoints - foreach (var sp in sPoints) { - if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && doRemoveBranches(sp)) { - sp.BranchPoints = emptyBranchList; - } + foreach (var sp in method.SequencePoints) { + if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && doRemoveBranches(sp)) { + sp.BranchPoints = emptyBranchList; + } } #endregion @@ -493,7 +404,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) var validBranchPoints = new List(); var branchExits = new Dictionary(); - foreach (var sp in sPoints) { + foreach (var sp in method.SequencePoints) { // SequencePoint has branches attached? if (sp.BranchPoints != null && sp.BranchPoints.Count != 0) { @@ -508,7 +419,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) } } - // Update SequencePoint properties/attributes + // Update SequencePoint counters sp.BranchExitsCount = 0; sp.BranchExitsVisit = 0; foreach (var branchPoint in branchExits.Values) { @@ -516,14 +427,14 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; } - // Add validBranchPoints - validBranchPoints.AddRange(sp.BranchPoints); - sp.BranchPoints = emptyBranchList; // clear + // Add to validBranchPoints + validBranchPoints.AddRange(sp.BranchPoints); + sp.BranchPoints = emptyBranchList; // clear } } // Replace original branchPoints with branches connected to sequence point(s) - bPoints = validBranchPoints.ToArray(); + method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); validBranchPoints = emptyBranchList; // clear #endregion @@ -537,10 +448,10 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) method.Visited = (method.MethodPoint.VisitCount > 0); } - method.Summary.NumBranchPoints = bPoints.Count(); - method.Summary.VisitedBranchPoints = bPoints.Count(pt => pt.VisitCount != 0); - method.Summary.NumSequencePoints = sPoints.Count(); - method.Summary.VisitedSequencePoints = sPoints.Count(pt => pt.VisitCount != 0); + method.Summary.NumBranchPoints = method.BranchPoints.Count(); + method.Summary.VisitedBranchPoints = method.BranchPoints.Count(pt => pt.VisitCount != 0); + method.Summary.NumSequencePoints = method.SequencePoints.Count(); + method.Summary.VisitedSequencePoints = method.SequencePoints.Count(pt => pt.VisitCount != 0); if (method.Summary.NumSequencePoints > 0) method.Summary.NumBranchPoints += 1; From 635e99eea1328a0a440d40c0a9bac29d2398d6b1 Mon Sep 17 00:00:00 2001 From: ddur Date: Wed, 16 Dec 2015 13:09:38 +0100 Subject: [PATCH 30/41] Enable Contract.EnsuresOnThrow, add comments --- .../Persistance/BasePersistance.cs | 65 +++++++++++++------ 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index bf18d2a87..8f8416e6d 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -55,7 +55,7 @@ public void PersistModule(Module module) { if (!existingModule.Aliases.Any(x=>x.Equals(module.FullName, StringComparison.InvariantCultureIgnoreCase))) { - existingModule.Aliases.Add(module.FullName); + existingModule.Aliases.Add(module.FullName); } return; } @@ -78,12 +78,12 @@ protected void ClearCoverageSession() } /// - /// + /// /// /// protected void ReassignCoverageSession(CoverageSession session) { - _moduleMethodMap.Clear(); + _moduleMethodMap.Clear(); CoverageSession = session; CoverageSession.Summary = new Summary(); foreach (var module in CoverageSession.Modules) @@ -132,7 +132,7 @@ private void BuildMethodMapForModule(Module module) /// public bool IsTracking(string modulePath) { - return CoverageSession.Modules.Any(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase)) && + return CoverageSession.Modules.Any(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase)) && !x.ShouldSerializeSkippedDueTo()); } @@ -225,7 +225,7 @@ private void RemoveUnreferencedFiles() if (CoverageSession.Modules == null) return; foreach (var module in CoverageSession.Modules) { - module.Files = (from file in module.Files ?? new File[0] + module.Files = (from file in module.Files ?? new File[0] from @class in module.Classes ?? new Class[0] where (@class.Methods ?? new Method[0]).Where(x=>x.FileRef != null).Any(x => x.FileRef.UniqueId == file.UniqueId) select file).Distinct().ToArray(); @@ -233,7 +233,7 @@ private void RemoveUnreferencedFiles() } // static readonly empty collections, saves creation time of new empty ones - private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; + private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; private static readonly List emptyBranchList = new List(0); @@ -241,11 +241,13 @@ private void RemoveUnreferencedFiles() private Dictionary sourceRepository = new Dictionary(); // match Contract.Requires<*> ( - private static Regex cRequiresMatch = new Regex (@"Contract\s*\.\s*Requires\s*<.+>\s*\(", RegexOptions.Compiled); + private static Regex cRequiresThrowMatch = new Regex (@"Contract\s*\.\s*Requires\s*<.+>\s*\(", RegexOptions.Compiled); // match Contract.Invariant ( private static Regex cInvariantMatch = new Regex (@"Contract\s*\.\s*Invariant\s*\(", RegexOptions.Compiled); // match Contract.Ensures[OnThrow<*>] ( - private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*(Ensures|EnsuresOnThrow\s*<.+>)\s*\(", RegexOptions.Compiled); + private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*Ensures\s*<.+>\s*\(", RegexOptions.Compiled); + // match Contract.EnsuresOnThrow<*>] ( + private static Regex cEnsuresOnThrowMatch = new Regex (@"Contract\s*\.\s*EnsuresOnThrow\s*<.+>\s*\(", RegexOptions.Compiled); private const bool doRemove = true; private const bool preserve = false; @@ -280,6 +282,14 @@ private bool doRemoveBranches (SequencePoint sp) { #endif } + /* Must exclude only SequencePoints that cannot have user defined branches + * Another approach by including (selecting) only lines with branches + * cannot be done by Regex for at least one reason + * 1) "for" keyword has no SequencePoint (undetectable), + * "for" branch is in second SequencePoint "[condition]" of + * "for ( [initialisation] ; [condition] ; [iteration] ) { .... + * and "[condition]" can be a boolean function (boolean undetectable by Regex) + */ string spSource = source.GetText (sp); if (String.IsNullOrWhiteSpace (spSource)) return doRemove; @@ -296,8 +306,8 @@ private bool doRemoveBranches (SequencePoint sp) { // ensuresOnThrow(x); // 12345678901234567890 if (spSource.Length >= 20 && spSource.Substring(0, 8) == "Contract" && spSource.Last() == ';') { -// if (cRequiresMatch.IsMatch (spSource)) -// return doRemove; + // Requires and EnsuresOnThrow branches are testable + // Requires sometimes has too much branches? if (cInvariantMatch.IsMatch (spSource)) return doRemove; if (cEnsuresMatch.IsMatch (spSource)) @@ -373,19 +383,30 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #region Join Sequences and Branches // Quick match branches to sequence using SP&BP sort order by IL offset - // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset + // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset // ATTN: Sorted again to prevent future bugs if order of SP & BP is changed! method.SequencePoints = method.SequencePoints.OrderBy( sp => sp.Offset ).ToArray(); method.BranchPoints = method.BranchPoints.OrderBy( bp => bp.Offset ).ToArray(); - var branchStack = new Stack(method.BranchPoints); // Stack.Pop is constant time - foreach (SequencePoint sPoint in method.SequencePoints.Reverse()) { - sPoint.BranchPoints = new List(); - while (branchStack.Count != 0 && branchStack.Peek().Offset >= sPoint.Offset) { - sPoint.BranchPoints.Add(branchStack.Pop()); + // Use stack because Stack.Pop is constant time + var branchStack = new Stack(method.BranchPoints); + + // Join offset matching BranchPoints with SequencePoint "parent" + // Exclude all branches where BranchPoint.Offset < first method.SequencePoints.Offset + // Reverse() starts loop from highest offset to lowest + foreach (SequencePoint spParent in method.SequencePoints.Reverse()) { + // create branchPoints "child" list + spParent.BranchPoints = new List(); + // if BranchPoint.Offset is >= SequencePoint.Offset + // then move BranchPoint from stack to "child" list (Pop/Add) + while (branchStack.Count != 0 && branchStack.Peek().Offset >= spParent.Offset) { + spParent.BranchPoints.Add(branchStack.Pop()); } } + // clear the stack + branchStack.Clear(); + #endregion #region Remove Compiler Generated Branches from SequencePoints @@ -398,7 +419,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #endregion - #region Merge Branch-Exits for each Sequence + #region Merge Branch-Exits for each Sequence // Collection of validBranchPoints (child/connected to parent SequencePoint) var validBranchPoints = new List(); @@ -433,7 +454,9 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) } } - // Replace original branchPoints with branches connected to sequence point(s) + // Replace original method branchPoints with valid (filtered and joined) branches. + // Order is Required by FilePersistanceTest because it does not sets .Offset. + // (Order by UniqueSequencePoint is equal to order by .Offset when .Offset is set) method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); validBranchPoints = emptyBranchList; // clear @@ -480,7 +503,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) @class.Summary.MaxCyclomaticComplexity = Math.Max(@class.Summary.MaxCyclomaticComplexity, method.CyclomaticComplexity); } - @class.Summary.NumClasses = (@class.Summary.NumMethods > 0) ? 1 : 0; + @class.Summary.NumClasses = (@class.Summary.NumMethods > 0) ? 1 : 0; @class.Summary.VisitedClasses = (@class.Summary.VisitedMethods > 0) ? 1 : 0; AddPoints(module.Summary, @class.Summary); @@ -562,7 +585,7 @@ public bool GetSequencePointsForFunction(string modulePath, int functionToken, o sequencePoints = points.ToArray(); return true; } - return false; + return false; } /// @@ -639,7 +662,7 @@ public void SaveVisitData(byte[] data) { if (!InstrumentationPoint.AddVisitCount(spid, _trackedMethodId)) { - _logger.ErrorFormat("Failed to add a visit to {0} with tracking method {1}. Max point count is {2}", + _logger.ErrorFormat("Failed to add a visit to {0} with tracking method {1}. Max point count is {2}", spid, _trackedMethodId, InstrumentationPoint.Count); } } From 1aa55127a337d8822334bb5b46c040bc1051e0ed Mon Sep 17 00:00:00 2001 From: ddur Date: Wed, 16 Dec 2015 14:52:22 +0100 Subject: [PATCH 31/41] Echo date&time (for local use) --- Build.bat | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Build.bat b/Build.bat index e1cf94e3b..22395e025 100644 --- a/Build.bat +++ b/Build.bat @@ -1,2 +1,6 @@ @echo off -build\nant-0.91-alpha2\bin\nant.exe -f:"%cd%"\default.build %1 \ No newline at end of file +build\nant-0.91-alpha2\bin\nant.exe -f:"%cd%"\default.build %1 +@echo. +@echo %date% +@echo %time% +@echo. \ No newline at end of file From f905078e106252bf70adad2c5ae47c930ebb2cc0 Mon Sep 17 00:00:00 2001 From: ddur Date: Thu, 17 Dec 2015 02:44:03 +0100 Subject: [PATCH 32/41] Remove all Contract branches AFAIK so far, no Contract.* method contains user branches that can be covered by test! --- .../Persistance/BasePersistance.cs | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 8f8416e6d..c21c7db22 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -240,14 +240,10 @@ private void RemoveUnreferencedFiles() // Dictionary with stored source files per module private Dictionary sourceRepository = new Dictionary(); - // match Contract.Requires<*> ( - private static Regex cRequiresThrowMatch = new Regex (@"Contract\s*\.\s*Requires\s*<.+>\s*\(", RegexOptions.Compiled); - // match Contract.Invariant ( - private static Regex cInvariantMatch = new Regex (@"Contract\s*\.\s*Invariant\s*\(", RegexOptions.Compiled); - // match Contract.Ensures[OnThrow<*>] ( - private static Regex cEnsuresMatch = new Regex (@"Contract\s*\.\s*Ensures\s*<.+>\s*\(", RegexOptions.Compiled); - // match Contract.EnsuresOnThrow<*>] ( - private static Regex cEnsuresOnThrowMatch = new Regex (@"Contract\s*\.\s*EnsuresOnThrow\s*<.+>\s*\(", RegexOptions.Compiled); + private static RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; + + // Match any Contract (Contract){1}(\s*\.\s*.+?){1}(\s*<.+>){1}?(\s*\(){1} + private static Regex contractMatch = new Regex (@"\A(Contract){1}(\s*\.\s*.+?){1}(\s*<.+>){1}?(\s*\(){1}", regexOptions); private const bool doRemove = true; private const bool preserve = false; @@ -305,12 +301,9 @@ private bool doRemoveBranches (SequencePoint sp) { // ensures(x); // ensuresOnThrow(x); // 12345678901234567890 - if (spSource.Length >= 20 && spSource.Substring(0, 8) == "Contract" && spSource.Last() == ';') { - // Requires and EnsuresOnThrow branches are testable - // Requires sometimes has too much branches? - if (cInvariantMatch.IsMatch (spSource)) - return doRemove; - if (cEnsuresMatch.IsMatch (spSource)) + if (spSource.Length >= 20 && spSource.Substring(0, 8) == "Contract") { + // No Contract.* method contains user branches that can be covered by test! + if (contractMatch.IsMatch (spSource)) return doRemove; } break; From 47874d57014a49ffefdf6c3a65205b1effcf51e7 Mon Sep 17 00:00:00 2001 From: ddur Date: Thu, 17 Dec 2015 21:48:53 +0100 Subject: [PATCH 33/41] Remove Regex Match, Exclude BP's by Offset --- .../Persistance/BasePersistance.cs | 134 +++++++++--------- 1 file changed, 65 insertions(+), 69 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index c21c7db22..5da7d055b 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; using OpenCover.Framework.Communication; @@ -240,77 +241,44 @@ private void RemoveUnreferencedFiles() // Dictionary with stored source files per module private Dictionary sourceRepository = new Dictionary(); - private static RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; - - // Match any Contract (Contract){1}(\s*\.\s*.+?){1}(\s*<.+>){1}?(\s*\(){1} - private static Regex contractMatch = new Regex (@"\A(Contract){1}(\s*\.\s*.+?){1}(\s*<.+>){1}?(\s*\(){1}", regexOptions); - private const bool doRemove = true; private const bool preserve = false; - //private static readonly ILog Logger = LogManager.GetLogger("OpenCover"); - - // Return true if branches can be removed - private bool doRemoveBranches (SequencePoint sp) { - - if (sp == null) - return preserve; - if (sp.FileId == 0) - return preserve; - + private uint fileID_cache = 0; + private CodeCoverageStringTextSource textSource_cache = null; + private CodeCoverageStringTextSource getCodeCoverageStringTextSource (uint fileId) { CodeCoverageStringTextSource source = null; - sourceRepository.TryGetValue (sp.FileId, out source); - if (source == null) - return preserve; - - switch (source.FileType) { - case FileType.Unsupported: - return preserve; - case FileType.CSharp: - break; // continue - case FileType.VBasic: - return preserve; - default: -#if DEBUG - throw new NotImplementedException ("Source.FileType"); -#else - return preserve; -#endif + if (fileId != 0) { + if (fileID_cache == fileId) { + source = textSource_cache; + } else { + sourceRepository.TryGetValue (fileId, out source); + if (source != null) { + fileID_cache = fileId; + textSource_cache = source; + } + } } + return source; + } - /* Must exclude only SequencePoints that cannot have user defined branches - * Another approach by including (selecting) only lines with branches - * cannot be done by Regex for at least one reason - * 1) "for" keyword has no SequencePoint (undetectable), - * "for" branch is in second SequencePoint "[condition]" of - * "for ( [initialisation] ; [condition] ; [iteration] ) { .... - * and "[condition]" can be a boolean function (boolean undetectable by Regex) - */ - string spSource = source.GetText (sp); - if (String.IsNullOrWhiteSpace (spSource)) - return doRemove; - - switch (spSource.Length) { - case 1: - if (spSource == "{" || spSource == "}") return doRemove; - break; - default: - // contract. - // requires(x); - // invariant(x); - // ensures(x); - // ensuresOnThrow(x); - // 12345678901234567890 - if (spSource.Length >= 20 && spSource.Substring(0, 8) == "Contract") { - // No Contract.* method contains user branches that can be covered by test! - if (contractMatch.IsMatch (spSource)) - return doRemove; - } - break; + private string getSequencePointText (SequencePoint sp) { + if (sp != null) { + CodeCoverageStringTextSource source = getCodeCoverageStringTextSource (sp.FileId); + return source != null ? source.GetText(sp) : ""; } - return preserve; + return ""; } + private static bool isSingleCharSequencePoint (SequencePoint sp) { + return ((sp != null) && (sp.StartLine == sp.EndLine) && (sp.EndColumn - sp.StartColumn) == 1); + } + private bool isLeftBraceSequencePoint (SequencePoint sp) { + return isSingleCharSequencePoint(sp) && getSequencePointText(sp) == "{"; + } + private bool isRightBraceSequencePoint (SequencePoint sp) { + return isSingleCharSequencePoint(sp) && getSequencePointText(sp) == "}"; + } private void PopulateInstrumentedPoints() { @@ -332,10 +300,11 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) foreach (var module in CoverageSession.Modules.Where(x => !x.ShouldSerializeSkippedDueTo())) { - #region Module File/FileID Dictionary + #region Module FileID/FullPath/TextSource sourceRepository = new Dictionary(); var filesDictionary = new Dictionary(); + foreach (var file in (module.Files ?? new File[0]).Where(file => !String.IsNullOrWhiteSpace(file.FullPath) && !filesDictionary.ContainsKey(file.FullPath))) { var source = CodeCoverageStringTextSource.GetSource(file.FullPath); @@ -345,7 +314,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #endregion - #region TODO:? Merge Compiler Extracted/Generated Methods (enumerator methods) + #region TODO:? Merge Compiler Extracted/Generated Methods (enumerator methods) SP's into method SP's // Store repeated Query var classesQuery = (module.Classes ?? new Class[0]).Where(x => !x.ShouldSerializeSkippedDueTo()); @@ -388,9 +357,9 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) // Exclude all branches where BranchPoint.Offset < first method.SequencePoints.Offset // Reverse() starts loop from highest offset to lowest foreach (SequencePoint spParent in method.SequencePoints.Reverse()) { - // create branchPoints "child" list + // create branchPoints "child" list spParent.BranchPoints = new List(); - // if BranchPoint.Offset is >= SequencePoint.Offset + // if BranchPoint.Offset is >= SequencePoint.Offset // then move BranchPoint from stack to "child" list (Pop/Add) while (branchStack.Count != 0 && branchStack.Peek().Offset >= spParent.Offset) { spParent.BranchPoints.Add(branchStack.Pop()); @@ -404,9 +373,33 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #region Remove Compiler Generated Branches from SequencePoints - foreach (var sp in method.SequencePoints) { - if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && doRemoveBranches(sp)) { - sp.BranchPoints = emptyBranchList; + long startOffset = long.MinValue; + long finalOffset = long.MaxValue; + CodeCoverageStringTextSource source = getCodeCoverageStringTextSource(method.FileRef.UniqueId); + if (source != null && source.FileType == FileType.CSharp) { + var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp=>sp.StartLine).ThenBy(sp=>sp.StartColumn).Where(sp=>sp.FileId == method.FileRef.UniqueId).ToArray(); + if (sourceLineOrderedSps.Length >= 3) { // method.sp; leftBrace.sp, rightBrace.sp || leftBrace.sp, any.sp, rightBrace.sp + if (isLeftBraceSequencePoint(sourceLineOrderedSps[1])) { + startOffset = sourceLineOrderedSps[1].Offset; + } + else if (isLeftBraceSequencePoint(sourceLineOrderedSps[0])) { + startOffset = sourceLineOrderedSps[0].Offset; + } + if (isRightBraceSequencePoint(sourceLineOrderedSps.Last())) { + finalOffset = sourceLineOrderedSps.Last().Offset; + } + } + } + + if (startOffset != long.MinValue || finalOffset != long.MaxValue) { + // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset + // this will exclude "{" "}" compiler generated branches and ccrewrite Code Contract's + foreach (var sp in method.SequencePoints) { + if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && sp.FileId == method.FileRef.UniqueId) { + if (sp.Offset <= startOffset || finalOffset <= sp.Offset) { + sp.BranchPoints = emptyBranchList; + } + } } } @@ -517,6 +510,9 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) CoverageSession.Summary.MinCyclomaticComplexity = Math.Min(CoverageSession.Summary.MinCyclomaticComplexity, module.Summary.MinCyclomaticComplexity); CoverageSession.Summary.MaxCyclomaticComplexity = Math.Max(CoverageSession.Summary.MaxCyclomaticComplexity, module.Summary.MaxCyclomaticComplexity); + + filesDictionary.Clear(); + sourceRepository.Clear(); } CalculateCoverage(CoverageSession.Summary); From 685bfdb785531f547b9d940b57b3ed77e88bbe76 Mon Sep 17 00:00:00 2001 From: molnargab Date: Sun, 20 Dec 2015 02:20:51 +0100 Subject: [PATCH 34/41] add sleep if yielding the thread fails (avoids spinning the CPU) --- .../Manager/ProfilerManager.cs | 4 +-- .../OpenCover.Framework.csproj | 1 + .../Utility/ThreadHelper.cs | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 main/OpenCover.Framework/Utility/ThreadHelper.cs diff --git a/main/OpenCover.Framework/Manager/ProfilerManager.cs b/main/OpenCover.Framework/Manager/ProfilerManager.cs index 545776677..a3be4881e 100644 --- a/main/OpenCover.Framework/Manager/ProfilerManager.cs +++ b/main/OpenCover.Framework/Manager/ProfilerManager.cs @@ -151,7 +151,7 @@ private WaitCallback SaveVisitData(EventWaitHandle queueMgmt) { byte[] data; while (!_messageQueue.TryDequeue(out data)) - Thread.Yield(); + ThreadHelper.YieldOrSleep(100); _perfCounters.CurrentMemoryQueueSize = _messageQueue.Count; _perfCounters.IncrementBlocksReceived(); @@ -289,7 +289,7 @@ private WaitCallback ProcessBlock(ManagedBufferBlock block, { do { - Thread.Yield(); + ThreadHelper.YieldOrSleep(100); } while (_messageQueue.Count > 200); } break; diff --git a/main/OpenCover.Framework/OpenCover.Framework.csproj b/main/OpenCover.Framework/OpenCover.Framework.csproj index f001cdc48..bbb6f1c0a 100644 --- a/main/OpenCover.Framework/OpenCover.Framework.csproj +++ b/main/OpenCover.Framework/OpenCover.Framework.csproj @@ -148,6 +148,7 @@ + diff --git a/main/OpenCover.Framework/Utility/ThreadHelper.cs b/main/OpenCover.Framework/Utility/ThreadHelper.cs new file mode 100644 index 000000000..9643ea1bf --- /dev/null +++ b/main/OpenCover.Framework/Utility/ThreadHelper.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + +namespace OpenCover.Framework.Utility +{ + internal static class ThreadHelper + { + public static void YieldOrSleep(int millisecondsInTimeout) + { + if (!Thread.Yield()) + { + Thread.Sleep(millisecondsInTimeout); + } + } + + public static void YieldOrSleep(TimeSpan timespan) + { + if (!Thread.Yield()) + { + Thread.Sleep(timespan); + } + } + } +} From 9f2bc789f4897927ffb4902ea15c33106d66b868 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 21 Dec 2015 16:38:06 +0000 Subject: [PATCH 35/41] #376 use concurrent map --- .../ProfilerCommunication.cpp | 32 +++++----- .../ProfilerCommunication.h | 9 ++- .../Integration/ThreadingTests.cs | 58 +++++++++++++++++++ main/OpenCover.Test/OpenCover.Test.csproj | 1 + 4 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 main/OpenCover.Test/Integration/ThreadingTests.cs diff --git a/main/OpenCover.Profiler/ProfilerCommunication.cpp b/main/OpenCover.Profiler/ProfilerCommunication.cpp index 92af54b6c..03ca3def2 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.cpp +++ b/main/OpenCover.Profiler/ProfilerCommunication.cpp @@ -194,35 +194,34 @@ bool ProfilerCommunication::Initialise(TCHAR *key, TCHAR *ns, TCHAR *processName } void ProfilerCommunication::ThreadCreated(ThreadID threadID, DWORD osThreadID){ - ATL::CComCritSecLock lock(_critThreads); _threadmap[threadID] = osThreadID; AllocateVisitMap(osThreadID); } MSG_SendVisitPoints_Request* ProfilerCommunication::AllocateVisitMap(DWORD osThreadID){ - auto p = new MSG_SendVisitPoints_Request(); - p->count = 0; - //::ZeroMemory(p, sizeof(MSG_SendVisitPoints_Request)); - _visitmap[osThreadID] = p; - return p; + ATL::CComCritSecLock lock(_critThreads); + auto it = _visitmap.find(osThreadID); + if (it == _visitmap.end() || it->second == nullptr) + { + auto p = new MSG_SendVisitPoints_Request(); + p->count = 0; + _visitmap[osThreadID] = p; + return p; + } + return it->second; } MSG_SendVisitPoints_Request* ProfilerCommunication::GetVisitMapForOSThread(ULONG osThreadID){ - MSG_SendVisitPoints_Request * p; auto it = _visitmap.find(osThreadID); - if (it == _visitmap.end()) { - ATL::CComCritSecLock lock(_critThreads); - it = _visitmap.find(osThreadID); - if (it == _visitmap.end()) { - return AllocateVisitMap(osThreadID); - } + if (it == _visitmap.end() || it->second == nullptr) { + return AllocateVisitMap(osThreadID); } return it->second; } void ProfilerCommunication::ThreadDestroyed(ThreadID threadID){ ATL::CComCritSecLock lock(_critThreads); - ULONG osThreadId = _threadmap[threadID]; + auto osThreadId = _threadmap[threadID]; auto points = _visitmap[osThreadId]; SendThreadVisitPoints(points); delete _visitmap[osThreadId]; @@ -230,24 +229,21 @@ void ProfilerCommunication::ThreadDestroyed(ThreadID threadID){ } void ProfilerCommunication::SendRemainingThreadBuffers(){ - ATL::CComCritSecLock lock(_critThreads); for (auto it = _visitmap.begin(); it != _visitmap.end(); ++it){ if (it->second != nullptr){ SendThreadVisitPoints(it->second); - //::ZeroMemory(pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); } } } void ProfilerCommunication::AddVisitPointToThreadBuffer(ULONG uniqueId, MSG_IdType msgType) { - DWORD osThreadId = ::GetCurrentThreadId(); + auto osThreadId = ::GetCurrentThreadId(); auto pVisitPoints = GetVisitMapForOSThread(osThreadId); pVisitPoints->points[pVisitPoints->count].UniqueId = (uniqueId | msgType); if (++pVisitPoints->count == VP_BUFFER_SIZE) { SendThreadVisitPoints(pVisitPoints); - //::ZeroMemory(pVisitPoints, sizeof(MSG_SendVisitPoints_Request)); } } diff --git a/main/OpenCover.Profiler/ProfilerCommunication.h b/main/OpenCover.Profiler/ProfilerCommunication.h index c07341d29..04759ce92 100644 --- a/main/OpenCover.Profiler/ProfilerCommunication.h +++ b/main/OpenCover.Profiler/ProfilerCommunication.h @@ -11,7 +11,7 @@ #include -#include +#include /// Handles communication back to the profiler host /// Currently this is handled by using the WebServices API @@ -95,8 +95,11 @@ class ProfilerCommunication private: ATL::CComAutoCriticalSection _critThreads; - std::unordered_map _threadmap; - std::unordered_map _visitmap; + //std::unordered_map _threadmap; + //std::unordered_map _visitmap; + + Concurrency::concurrent_unordered_map _threadmap; + Concurrency::concurrent_unordered_map _visitmap; MSG_SendVisitPoints_Request* GetVisitMapForOSThread(ULONG osThread); diff --git a/main/OpenCover.Test/Integration/ThreadingTests.cs b/main/OpenCover.Test/Integration/ThreadingTests.cs new file mode 100644 index 000000000..af48c7148 --- /dev/null +++ b/main/OpenCover.Test/Integration/ThreadingTests.cs @@ -0,0 +1,58 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using NUnit.Framework; +using OpenCover.Framework; + +namespace OpenCover.Test.Integration +{ + /// + /// Replicates issue with threads as reported in issue #366 + /// + [TestFixture] + public class ThreadingTests + { + const int NB_THREADS = 50; + static readonly ManualResetEvent[] ResetEvents = new ManualResetEvent[NB_THREADS]; + + [Test] + public void RunManyThreads() + { + //Thread.Sleep(15000); + for (int i = 0; i < NB_THREADS; i++) + { + ResetEvents[i] = new ManualResetEvent(false); + new Thread(DoWork).Start(ResetEvents[i]); + } + var chrono = Stopwatch.StartNew(); + long n = 0; + while (n < 2000) + { + if (++n % 200 == 0) + Console.WriteLine(n.ToString()); + var current = WaitHandle.WaitAny(ResetEvents.ToArray()); + ResetEvents[current].Reset(); + new Thread(DoWork).Start(ResetEvents[current]); + } + Console.WriteLine("Took {0} seconds", chrono.Elapsed.TotalSeconds); + Assert.Pass(); + } + + public static void DoWork(object o) + { + var resetEvent = (ManualResetEvent)o; + resetEvent.Do(re => + { + var rnd = new Random(); + double res = 0; + for (var i = 0; i < 10000; i++) + res += rnd.NextDouble(); + re.Set(); + }); + + + } + + } +} diff --git a/main/OpenCover.Test/OpenCover.Test.csproj b/main/OpenCover.Test/OpenCover.Test.csproj index fb09b74b3..755e145ef 100644 --- a/main/OpenCover.Test/OpenCover.Test.csproj +++ b/main/OpenCover.Test/OpenCover.Test.csproj @@ -167,6 +167,7 @@ + From 1370d0469f9aaa8cf97de1ef26d0ad0a65c03aa6 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 21 Dec 2015 16:41:34 +0000 Subject: [PATCH 36/41] fix spelling mistake --- main/OpenCover.Console/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/OpenCover.Console/Program.cs b/main/OpenCover.Console/Program.cs index 1a23ecfac..328641ee3 100644 --- a/main/OpenCover.Console/Program.cs +++ b/main/OpenCover.Console/Program.cs @@ -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); From f7aa1656cf96490c54594f324a7de04fae8148d4 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 21 Dec 2015 17:16:41 +0000 Subject: [PATCH 37/41] update notes --- ReleaseNotes.tmp | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseNotes.tmp b/ReleaseNotes.tmp index f4a23025f..399c86ba9 100644 --- a/ReleaseNotes.tmp +++ b/ReleaseNotes.tmp @@ -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) From 54c551bc4efb45b505b5f29297dd1f28b63be510 Mon Sep 17 00:00:00 2001 From: sawilde Date: Mon, 21 Dec 2015 17:47:55 +0000 Subject: [PATCH 38/41] #366 add lock protection over around Module.Alias access by base persistence --- .../Persistance/BasePersistance.cs | 136 ++++++++++-------- 1 file changed, 75 insertions(+), 61 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 33d30a28c..ef41ef36a 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Text.RegularExpressions; using OpenCover.Framework.Communication; using OpenCover.Framework.Model; using OpenCover.Framework.Utility; @@ -15,6 +13,9 @@ namespace OpenCover.Framework.Persistance /// public abstract class BasePersistance : IPersistance { + + private static readonly object Protection = new object(); + /// /// Provides subclasses access to the command line object /// @@ -53,15 +54,23 @@ public void PersistModule(Module module) module.Classes = module.Classes ?? new Class[0]; if (CommandLine.MergeByHash) { - var modules = CoverageSession.Modules ?? new Module[0]; - var existingModule = modules.FirstOrDefault(x => x.ModuleHash == module.ModuleHash); - if (existingModule!=null) + lock (Protection) { - if (!existingModule.Aliases.Any(x=>x.Equals(module.FullName, StringComparison.InvariantCultureIgnoreCase))) + var modules = CoverageSession.Modules ?? new Module[0]; + lock (Protection) { - existingModule.Aliases.Add(module.FullName); + var existingModule = modules.FirstOrDefault(x => x.ModuleHash == module.ModuleHash); + if (existingModule != null) + { + if ( + !existingModule.Aliases.Any( + x => x.Equals(module.FullName, StringComparison.InvariantCultureIgnoreCase))) + { + existingModule.Aliases.Add(module.FullName); + } + return; + } } - return; } } @@ -136,8 +145,10 @@ private void BuildMethodMapForModule(Module module) /// public bool IsTracking(string modulePath) { - return CoverageSession.Modules.Any(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase)) && - !x.ShouldSerializeSkippedDueTo()); + lock (Protection) { + return CoverageSession.Modules.Any(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase)) && + !x.ShouldSerializeSkippedDueTo()); + } } /// @@ -237,50 +248,47 @@ private void RemoveUnreferencedFiles() } // static readonly empty collections, saves creation time of new empty ones - private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; - private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; - private static readonly List emptyBranchList = new List(0); + private static readonly SequencePoint[] EmptySeqPoints = new SequencePoint[0]; + private static readonly BranchPoint[] EmptyBranchPoints = new BranchPoint[0]; + private static readonly List EmptyBranchList = new List(0); // Dictionary with stored source files per module - private Dictionary sourceRepository = new Dictionary(); + private Dictionary _sourceRepository = new Dictionary(); - private const bool doRemove = true; - private const bool preserve = false; - - private uint fileID_cache = 0; - private CodeCoverageStringTextSource textSource_cache = null; - private CodeCoverageStringTextSource getCodeCoverageStringTextSource (uint fileId) { + private uint _fileIdCache; + private CodeCoverageStringTextSource _textSourceCache; + private CodeCoverageStringTextSource GetCodeCoverageStringTextSource (uint fileId) { CodeCoverageStringTextSource source = null; if (fileId != 0) { - if (fileID_cache == fileId) { - source = textSource_cache; + if (_fileIdCache == fileId) { + source = _textSourceCache; } else { - sourceRepository.TryGetValue (fileId, out source); + _sourceRepository.TryGetValue (fileId, out source); if (source != null) { - fileID_cache = fileId; - textSource_cache = source; + _fileIdCache = fileId; + _textSourceCache = source; } } } return source; } - private string getSequencePointText (SequencePoint sp) { + private string GetSequencePointText (SequencePoint sp) { if (sp != null) { - CodeCoverageStringTextSource source = getCodeCoverageStringTextSource (sp.FileId); + CodeCoverageStringTextSource source = GetCodeCoverageStringTextSource (sp.FileId); return source != null ? source.GetText(sp) : ""; } return ""; } - private static bool isSingleCharSequencePoint (SequencePoint sp) { + private static bool IsSingleCharSequencePoint (SequencePoint sp) { return ((sp != null) && (sp.StartLine == sp.EndLine) && (sp.EndColumn - sp.StartColumn) == 1); } - private bool isLeftBraceSequencePoint (SequencePoint sp) { - return isSingleCharSequencePoint(sp) && getSequencePointText(sp) == "{"; + private bool IsLeftBraceSequencePoint (SequencePoint sp) { + return IsSingleCharSequencePoint(sp) && GetSequencePointText(sp) == "{"; } - private bool isRightBraceSequencePoint (SequencePoint sp) { - return isSingleCharSequencePoint(sp) && getSequencePointText(sp) == "}"; + private bool IsRightBraceSequencePoint (SequencePoint sp) { + return IsSingleCharSequencePoint(sp) && GetSequencePointText(sp) == "}"; } private void PopulateInstrumentedPoints() @@ -305,13 +313,13 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) #region Module FileID/FullPath/TextSource - sourceRepository = new Dictionary(); + _sourceRepository = new Dictionary(); var filesDictionary = new Dictionary(); foreach (var file in (module.Files ?? new File[0]).Where(file => !String.IsNullOrWhiteSpace(file.FullPath) && !filesDictionary.ContainsKey(file.FullPath))) { var source = CodeCoverageStringTextSource.GetSource(file.FullPath); - if (source != null) sourceRepository.Add (file.UniqueId, source); + if (source != null) _sourceRepository.Add (file.UniqueId, source); filesDictionary.Add(file.FullPath, file.UniqueId); } @@ -329,12 +337,12 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) foreach (var method in (@class.Methods ?? new Method[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) { - if (method.SequencePoints == null) method.SequencePoints = emptySeqPoints; - if (method.BranchPoints == null) method.BranchPoints = emptyBranchPoints; + if (method.SequencePoints == null) method.SequencePoints = EmptySeqPoints; + if (method.BranchPoints == null) method.BranchPoints = EmptyBranchPoints; // No sequences in method, but branches present? => remove branches if (method.SequencePoints.Length == 0 && method.BranchPoints.Length != 0) { - method.BranchPoints = emptyBranchPoints; + method.BranchPoints = EmptyBranchPoints; } if (method.SequencePoints.Length != 0) MapFileReferences(method.SequencePoints, filesDictionary); @@ -378,17 +386,17 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) long startOffset = long.MinValue; long finalOffset = long.MaxValue; - CodeCoverageStringTextSource source = getCodeCoverageStringTextSource(method.FileRef.UniqueId); + CodeCoverageStringTextSource source = GetCodeCoverageStringTextSource(method.FileRef.UniqueId); if (source != null && source.FileType == FileType.CSharp) { var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp=>sp.StartLine).ThenBy(sp=>sp.StartColumn).Where(sp=>sp.FileId == method.FileRef.UniqueId).ToArray(); if (sourceLineOrderedSps.Length >= 3) { // method.sp; leftBrace.sp, rightBrace.sp || leftBrace.sp, any.sp, rightBrace.sp - if (isLeftBraceSequencePoint(sourceLineOrderedSps[1])) { + if (IsLeftBraceSequencePoint(sourceLineOrderedSps[1])) { startOffset = sourceLineOrderedSps[1].Offset; } - else if (isLeftBraceSequencePoint(sourceLineOrderedSps[0])) { + else if (IsLeftBraceSequencePoint(sourceLineOrderedSps[0])) { startOffset = sourceLineOrderedSps[0].Offset; } - if (isRightBraceSequencePoint(sourceLineOrderedSps.Last())) { + if (IsRightBraceSequencePoint(sourceLineOrderedSps.Last())) { finalOffset = sourceLineOrderedSps.Last().Offset; } } @@ -400,7 +408,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) foreach (var sp in method.SequencePoints) { if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && sp.FileId == method.FileRef.UniqueId) { if (sp.Offset <= startOffset || finalOffset <= sp.Offset) { - sp.BranchPoints = emptyBranchList; + sp.BranchPoints = EmptyBranchList; } } } @@ -439,7 +447,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) // Add to validBranchPoints validBranchPoints.AddRange(sp.BranchPoints); - sp.BranchPoints = emptyBranchList; // clear + sp.BranchPoints = EmptyBranchList; // clear } } @@ -447,7 +455,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) // Order is Required by FilePersistanceTest because it does not sets .Offset. // (Order by UniqueSequencePoint is equal to order by .Offset when .Offset is set) method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); - validBranchPoints = emptyBranchList; // clear + validBranchPoints = EmptyBranchList; // clear #endregion @@ -515,7 +523,7 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) CoverageSession.Summary.MaxCyclomaticComplexity = Math.Max(CoverageSession.Summary.MaxCyclomaticComplexity, module.Summary.MaxCyclomaticComplexity); filesDictionary.Clear(); - sourceRepository.Clear(); + _sourceRepository.Clear(); } CalculateCoverage(CoverageSession.Summary); @@ -612,13 +620,17 @@ private Method GetMethod(string modulePath, int functionToken, out Class @class) { @class = null; //c = null; - var module = CoverageSession.Modules.FirstOrDefault(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase))); - if (module == null) - return null; - if (!_moduleMethodMap[module].ContainsKey(functionToken)) return null; - var pair = _moduleMethodMap[module][functionToken]; - @class = pair.Key; - return pair.Value; + lock (Protection) + { + var module = CoverageSession.Modules + .FirstOrDefault(x => x.Aliases.Any(path => path.Equals(modulePath, StringComparison.InvariantCultureIgnoreCase))); + if (module == null) + return null; + if (!_moduleMethodMap[module].ContainsKey(functionToken)) return null; + var pair = _moduleMethodMap[module][functionToken]; + @class = pair.Key; + return pair.Value; + } } /// @@ -676,21 +688,23 @@ public void SaveVisitData(byte[] data) /// public bool GetTrackingMethod(string modulePath, string assemblyName, int functionToken, out uint uniqueId) { - uniqueId = 0; - foreach (var module in CoverageSession.Modules - .Where(x => x.TrackedMethods != null) - .Where(x => x.Aliases.Contains(modulePath))) + lock (Protection) { - foreach (var trackedMethod in module.TrackedMethods) + uniqueId = 0; + foreach (var module in CoverageSession.Modules + .Where(x => x.TrackedMethods != null) + .Where(x => x.Aliases.Contains(modulePath))) { - if (trackedMethod.MetadataToken == functionToken) + foreach (var trackedMethod in module.TrackedMethods) { - uniqueId = trackedMethod.UniqueId; - return true; + if (trackedMethod.MetadataToken == functionToken) + { + uniqueId = trackedMethod.UniqueId; + return true; + } } } } - return false; } } From b57bdda47cd93ecf5e68da419cb856d352ec3374 Mon Sep 17 00:00:00 2001 From: ddur Date: Wed, 23 Dec 2015 18:50:31 +0100 Subject: [PATCH 39/41] Remove duplicate empty SequencePoint & Refactored --- main/OpenCover.Framework/Model/Method.cs | 47 ++ .../Model/SequencePoint.cs | 52 +- .../OpenCover.Framework.csproj | 1 + .../Persistance/BasePersistance.cs | 638 +++++++++++------- .../Symbols/CecilSymbolManager.cs | 3 +- .../Utility/SourceRepository.cs | 224 ++++++ 6 files changed, 722 insertions(+), 243 deletions(-) create mode 100644 main/OpenCover.Framework/Utility/SourceRepository.cs diff --git a/main/OpenCover.Framework/Model/Method.cs b/main/OpenCover.Framework/Model/Method.cs index afb790437..190dd056c 100644 --- a/main/OpenCover.Framework/Model/Method.cs +++ b/main/OpenCover.Framework/Model/Method.cs @@ -3,7 +3,9 @@ // // This source code is released under the MIT License; see the accompanying license file. // +using System; using System.Collections.Generic; +using System.Text.RegularExpressions; using System.Xml.Serialization; namespace OpenCover.Framework.Model @@ -95,6 +97,10 @@ public class Method : SummarySkippedEntity [XmlAttribute("isSetter")] public bool IsSetter { get; set; } + /// + /// Mark As Skipped + /// + /// public override void MarkAsSkipped(SkippedMethod reason) { SkippedDueTo = reason; @@ -103,5 +109,46 @@ public override void MarkAsSkipped(SkippedMethod reason) SequencePoints = null; BranchPoints = null; } + /// + /// method name excluding return type, namespace and arguments + /// + public string shortName { + get { + if (String.IsNullOrWhiteSpace(this.Name)) return ""; + int startIndex = this.Name.IndexOf("::", StringComparison.Ordinal); + int finalIndex = this.Name.IndexOf('(', startIndex); + return this.Name + .Substring(startIndex, finalIndex - startIndex) + .Substring(2); + } + } + + /* Compiler Generated Name Examples + System.Boolean DD.Collections.BitSetArray/<Complement>d__e::MoveNext() + System.Boolean DD.Collections.BitSetArray::<_SetItems>b__b(System.Int32) + System.Boolean DD.Collections.BitSetArray::BitSetArray_<_SetItems>b__b_0(System.Int32) + + [^\s]+\s[^\s|/|:]+(/\w*)?(::(.+_)?)?(<\w+>[a-z]__\w(\w|_\w)?)(::.+)?(\(.*\))$ + */ + /// + /// True if method name matches isGeneratedMethodRegex pattern + /// + public bool isGenerated { + get { + return (!String.IsNullOrWhiteSpace(this.Name) + && this.Name.Contains("__") + && isGeneratedMethodRegex.IsMatch(this.Name) + ); + } + } + private const RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; + private readonly Regex isGeneratedMethodRegex = new Regex(@"(<[^\s|>]+>[a-z]__\w(\w|_\w)?)(::([^\s|\(]+))?(\([^\s|\)]*\))$", regexOptions); + + /* + code sample + Match match = generatedMethodItems.Match(sample); + if (match.Success) Console.WriteLine(match.Groups["returnType"].Value); + */ + private readonly Regex generatedMethodItems = new Regex(@"(?[^\s]+)\s(?[^\s|/]+/)?(?[^\s|:]+::)?(<(?[^\s|>]+)>[a-z]__\w(\w|_\w)?)(::(?[^\s|\(]+))?(\([^\s|\)]*\))$", regexOptions); } } diff --git a/main/OpenCover.Framework/Model/SequencePoint.cs b/main/OpenCover.Framework/Model/SequencePoint.cs index f0a556f17..a801de494 100644 --- a/main/OpenCover.Framework/Model/SequencePoint.cs +++ b/main/OpenCover.Framework/Model/SequencePoint.cs @@ -4,6 +4,7 @@ // This source code is released under the MIT License; see the accompanying license file. // +using System; using System.Collections.Generic; using System.Xml.Serialization; @@ -12,7 +13,7 @@ namespace OpenCover.Framework.Model /// /// a sequence point /// - public class SequencePoint : InstrumentationPoint, IDocumentReference + public class SequencePoint : InstrumentationPoint, IDocumentReference, IEquatable { /// /// The start line of the sequence point @@ -63,5 +64,54 @@ public class SequencePoint : InstrumentationPoint, IDocumentReference public string Document { get; set; } internal List BranchPoints { get; set; } + + /// + /// Property + /// + public bool isSingleCharSequencePoint { + get { + return (this.StartLine == this.EndLine) && (this.EndColumn - this.StartColumn) == 1; + } + } + + #region IEquatable implementation + + /// + /// Override GetHashCode + /// + /// int + public override int GetHashCode () { + return unchecked (this.StartLine << 3) ^ unchecked (this.EndLine << 2) ^ unchecked (this.StartColumn << 1) ^ (this.EndColumn); + } + + /// + /// Override Equals + /// + /// Object + /// bool + public override bool Equals (Object obj) { + if (ReferenceEquals(this, obj)) { + return true; + } + var that = obj as SequencePoint; + return !ReferenceEquals(that, null) && this.Equals(that); + } + + /// + /// IEquatable<SequencePoint>.Equals implementation + /// + /// SequencePoint + /// bool + bool IEquatable.Equals(SequencePoint other) + { + return !ReferenceEquals(other, null) + && this.Document == other.Document + && this.StartLine == other.StartLine + && this.StartColumn == other.StartColumn + && this.EndLine == other.EndLine + && this.EndColumn == other.EndColumn; + } + + #endregion } } diff --git a/main/OpenCover.Framework/OpenCover.Framework.csproj b/main/OpenCover.Framework/OpenCover.Framework.csproj index f001cdc48..5629413b7 100644 --- a/main/OpenCover.Framework/OpenCover.Framework.csproj +++ b/main/OpenCover.Framework/OpenCover.Framework.csproj @@ -148,6 +148,7 @@ + diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index 5da7d055b..b28d1385f 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; @@ -15,6 +16,9 @@ namespace OpenCover.Framework.Persistance /// public abstract class BasePersistance : IPersistance { + /// + /// ICommandLine + /// protected readonly ICommandLine CommandLine; private readonly ILog _logger; private uint _trackedMethodId; @@ -142,39 +146,47 @@ public bool IsTracking(string modulePath) /// public virtual void Commit() { - PopulateInstrumentedPoints(); + //ILog TempLogger = LogManager.GetLogger("OpenCover"); + //TempLogger.Info("Checking Coverage Session..."); + if (CoverageSession.Modules != null) { + //TempLogger.Info("MarkSkippedMethods..."); + MarkSkippedMethods(); + //TempLogger.Info("TransformSequences..."); + TransformSequences(); + //TempLogger.Info("CalculateCoverage..."); + CalculateCoverage(); + //TempLogger.Info("FilterSkippedMethods..."); + if (CommandLine.HideSkipped != null && CommandLine.HideSkipped.Any()) { + foreach (var skippedMethod in CommandLine.HideSkipped.OrderBy(x => x)) + { + switch (skippedMethod) + { + case SkippedMethod.File: + RemoveSkippedMethods(SkippedMethod.File); + RemoveEmptyClasses(); + RemoveUnreferencedFiles(); + break; + case SkippedMethod.Filter: + RemoveSkippedModules(SkippedMethod.Filter); + RemoveSkippedClasses(SkippedMethod.Filter); + break; + case SkippedMethod.MissingPdb: + RemoveSkippedModules(SkippedMethod.MissingPdb); + break; + case SkippedMethod.Attribute: + RemoveSkippedClasses(SkippedMethod.Attribute); + RemoveSkippedMethods(SkippedMethod.Attribute); + RemoveEmptyClasses(); + break; + case SkippedMethod.AutoImplementedProperty: + RemoveSkippedMethods(SkippedMethod.Attribute); + RemoveEmptyClasses(); + break; + } + } + } + } - if (CommandLine.HideSkipped == null) return; - - if (!CommandLine.HideSkipped.Any()) return; - - foreach (var skippedMethod in CommandLine.HideSkipped.OrderBy(x => x)) - { - switch (skippedMethod) - { - case SkippedMethod.File: - RemoveSkippedMethods(SkippedMethod.File); - RemoveEmptyClasses(); - RemoveUnreferencedFiles(); - break; - case SkippedMethod.Filter: - RemoveSkippedModules(SkippedMethod.Filter); - RemoveSkippedClasses(SkippedMethod.Filter); - break; - case SkippedMethod.MissingPdb: - RemoveSkippedModules(SkippedMethod.MissingPdb); - break; - case SkippedMethod.Attribute: - RemoveSkippedClasses(SkippedMethod.Attribute); - RemoveSkippedMethods(SkippedMethod.Attribute); - RemoveEmptyClasses(); - break; - case SkippedMethod.AutoImplementedProperty: - RemoveSkippedMethods(SkippedMethod.Attribute); - RemoveEmptyClasses(); - break; - } - } } private void RemoveSkippedModules(SkippedMethod skipped) @@ -233,58 +245,8 @@ private void RemoveUnreferencedFiles() } } - // static readonly empty collections, saves creation time of new empty ones - private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; - private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; - private static readonly List emptyBranchList = new List(0); - - // Dictionary with stored source files per module - private Dictionary sourceRepository = new Dictionary(); - - private const bool doRemove = true; - private const bool preserve = false; - - private uint fileID_cache = 0; - private CodeCoverageStringTextSource textSource_cache = null; - private CodeCoverageStringTextSource getCodeCoverageStringTextSource (uint fileId) { - CodeCoverageStringTextSource source = null; - if (fileId != 0) { - if (fileID_cache == fileId) { - source = textSource_cache; - } else { - sourceRepository.TryGetValue (fileId, out source); - if (source != null) { - fileID_cache = fileId; - textSource_cache = source; - } - } - } - return source; - } - - private string getSequencePointText (SequencePoint sp) { - if (sp != null) { - CodeCoverageStringTextSource source = getCodeCoverageStringTextSource (sp.FileId); - return source != null ? source.GetText(sp) : ""; - } - return ""; - } - - private static bool isSingleCharSequencePoint (SequencePoint sp) { - return ((sp != null) && (sp.StartLine == sp.EndLine) && (sp.EndColumn - sp.StartColumn) == 1); - } - private bool isLeftBraceSequencePoint (SequencePoint sp) { - return isSingleCharSequencePoint(sp) && getSequencePointText(sp) == "{"; - } - private bool isRightBraceSequencePoint (SequencePoint sp) { - return isSingleCharSequencePoint(sp) && getSequencePointText(sp) == "}"; - } - - private void PopulateInstrumentedPoints() - { - - if (CoverageSession.Modules == null) return; - + private void MarkSkippedMethods() + { foreach (var method in from @class in (from module in CoverageSession.Modules from @class in module.Classes ?? new Class[0] @@ -296,162 +258,16 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) { method.MarkAsSkipped(SkippedMethod.Inferred); } - + } + + private void CalculateCoverage() + { foreach (var module in CoverageSession.Modules.Where(x => !x.ShouldSerializeSkippedDueTo())) { - - #region Module FileID/FullPath/TextSource - - sourceRepository = new Dictionary(); - var filesDictionary = new Dictionary(); - - foreach (var file in (module.Files ?? new File[0]).Where(file => !String.IsNullOrWhiteSpace(file.FullPath) && !filesDictionary.ContainsKey(file.FullPath))) - { - var source = CodeCoverageStringTextSource.GetSource(file.FullPath); - if (source != null) sourceRepository.Add (file.UniqueId, source); - filesDictionary.Add(file.FullPath, file.UniqueId); - } - - #endregion - - #region TODO:? Merge Compiler Extracted/Generated Methods (enumerator methods) SP's into method SP's - - // Store repeated Query - var classesQuery = (module.Classes ?? new Class[0]).Where(x => !x.ShouldSerializeSkippedDueTo()); - - #endregion - - foreach (var @class in classesQuery) + foreach (var @class in (module.Classes ?? new Class[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) { - foreach (var method in (@class.Methods ?? new Method[0]).Where(x => !x.ShouldSerializeSkippedDueTo())) { - if (method.SequencePoints == null) method.SequencePoints = emptySeqPoints; - if (method.BranchPoints == null) method.BranchPoints = emptyBranchPoints; - - // No sequences in method, but branches present? => remove branches - if (method.SequencePoints.Length == 0 && method.BranchPoints.Length != 0) { - method.BranchPoints = emptyBranchPoints; - } - - if (method.SequencePoints.Length != 0) MapFileReferences(method.SequencePoints, filesDictionary); - if (method.BranchPoints.Length != 0) MapFileReferences(method.BranchPoints, filesDictionary); - - #region Merge branch-exits - - // anything to join, filter, merge? - if (method.SequencePoints.Length != 0 && method.BranchPoints.Length != 0) { - - #region Join Sequences and Branches - // Quick match branches to sequence using SP&BP sort order by IL offset - - // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset - // ATTN: Sorted again to prevent future bugs if order of SP & BP is changed! - method.SequencePoints = method.SequencePoints.OrderBy( sp => sp.Offset ).ToArray(); - method.BranchPoints = method.BranchPoints.OrderBy( bp => bp.Offset ).ToArray(); - - // Use stack because Stack.Pop is constant time - var branchStack = new Stack(method.BranchPoints); - - // Join offset matching BranchPoints with SequencePoint "parent" - // Exclude all branches where BranchPoint.Offset < first method.SequencePoints.Offset - // Reverse() starts loop from highest offset to lowest - foreach (SequencePoint spParent in method.SequencePoints.Reverse()) { - // create branchPoints "child" list - spParent.BranchPoints = new List(); - // if BranchPoint.Offset is >= SequencePoint.Offset - // then move BranchPoint from stack to "child" list (Pop/Add) - while (branchStack.Count != 0 && branchStack.Peek().Offset >= spParent.Offset) { - spParent.BranchPoints.Add(branchStack.Pop()); - } - } - - // clear the stack - branchStack.Clear(); - - #endregion - - #region Remove Compiler Generated Branches from SequencePoints - - long startOffset = long.MinValue; - long finalOffset = long.MaxValue; - CodeCoverageStringTextSource source = getCodeCoverageStringTextSource(method.FileRef.UniqueId); - if (source != null && source.FileType == FileType.CSharp) { - var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp=>sp.StartLine).ThenBy(sp=>sp.StartColumn).Where(sp=>sp.FileId == method.FileRef.UniqueId).ToArray(); - if (sourceLineOrderedSps.Length >= 3) { // method.sp; leftBrace.sp, rightBrace.sp || leftBrace.sp, any.sp, rightBrace.sp - if (isLeftBraceSequencePoint(sourceLineOrderedSps[1])) { - startOffset = sourceLineOrderedSps[1].Offset; - } - else if (isLeftBraceSequencePoint(sourceLineOrderedSps[0])) { - startOffset = sourceLineOrderedSps[0].Offset; - } - if (isRightBraceSequencePoint(sourceLineOrderedSps.Last())) { - finalOffset = sourceLineOrderedSps.Last().Offset; - } - } - } - - if (startOffset != long.MinValue || finalOffset != long.MaxValue) { - // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset - // this will exclude "{" "}" compiler generated branches and ccrewrite Code Contract's - foreach (var sp in method.SequencePoints) { - if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && sp.FileId == method.FileRef.UniqueId) { - if (sp.Offset <= startOffset || finalOffset <= sp.Offset) { - sp.BranchPoints = emptyBranchList; - } - } - } - } - - #endregion - - #region Merge Branch-Exits for each Sequence - - // Collection of validBranchPoints (child/connected to parent SequencePoint) - var validBranchPoints = new List(); - - var branchExits = new Dictionary(); - foreach (var sp in method.SequencePoints) { - - // SequencePoint has branches attached? - if (sp.BranchPoints != null && sp.BranchPoints.Count != 0) { - - // Merge sp.BranchPoints using EndOffset as branchExits key - branchExits.Clear(); - foreach (var branchPoint in sp.BranchPoints) { - if (!branchExits.ContainsKey(branchPoint.EndOffset)) { - branchExits[branchPoint.EndOffset] = branchPoint; // insert branch - } else { - branchExits[branchPoint.EndOffset].VisitCount += branchPoint.VisitCount; // update branch - } - } - - // Update SequencePoint counters - sp.BranchExitsCount = 0; - sp.BranchExitsVisit = 0; - foreach (var branchPoint in branchExits.Values) { - sp.BranchExitsCount += 1; - sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; - } - - // Add to validBranchPoints - validBranchPoints.AddRange(sp.BranchPoints); - sp.BranchPoints = emptyBranchList; // clear - } - } - - // Replace original method branchPoints with valid (filtered and joined) branches. - // Order is Required by FilePersistanceTest because it does not sets .Offset. - // (Order by UniqueSequencePoint is equal to order by .Offset when .Offset is set) - method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); - validBranchPoints = emptyBranchList; // clear - - #endregion - - } - - #endregion - if (method.MethodPoint != null) { method.Visited = (method.MethodPoint.VisitCount > 0); @@ -511,14 +327,11 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo()) CoverageSession.Summary.MinCyclomaticComplexity = Math.Min(CoverageSession.Summary.MinCyclomaticComplexity, module.Summary.MinCyclomaticComplexity); CoverageSession.Summary.MaxCyclomaticComplexity = Math.Max(CoverageSession.Summary.MaxCyclomaticComplexity, module.Summary.MaxCyclomaticComplexity); - filesDictionary.Clear(); - sourceRepository.Clear(); } - CalculateCoverage(CoverageSession.Summary); } - private static void MapFileReferences(IEnumerable points, IDictionary filesDictionary) + private static void MapFileReferences(IEnumerable points, IDictionary filesDictionary) { foreach (var pt in points.Where(p => p.FileId == 0)) { @@ -690,5 +503,348 @@ public bool GetTrackingMethod(string modulePath, string assemblyName, int functi return false; } - } -} \ No newline at end of file + + // static readonly empty collections, saves creation time of new empty ones + // do not modify when referenced/attached to parent + private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0]; + private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0]; + private static readonly List emptyBranchList = new List(0); + + private void TransformSequences() { + + var sessionModulesQuery = CoverageSession.Modules.Where(@module => !@module.ShouldSerializeSkippedDueTo()); + foreach(var module in sessionModulesQuery) { + + // module sources + var sourceRepository = new SourceRepository(); + + // Queries + var moduleClassesQuery = (module.Classes ?? new Class[0]).Where(x => !x.ShouldSerializeSkippedDueTo()); + var moduleMethodsQuery = moduleClassesQuery.SelectMany(@class => (@class.Methods ?? new Method[0])).Where(x => !x.ShouldSerializeSkippedDueTo()); + var methods = new ReadOnlyCollection(moduleMethodsQuery.ToArray()); + + #region Step 0: Collect Module Files (FileID/FullPath/TextSource) + + #endregion + + #region Step 1: Prepare sequences for transformations + TransformSequences_Initialize (methods); + TransformSequences_AddSources (module, methods, sourceRepository); + TransformSequences_JoinWithBranches (methods); + TransformSequences_RemoveBranchesOutOfOffset (methods, sourceRepository); + TransformSequences_NormalizeBranches (methods); + #endregion + + #region step 2: Transformations + TransformSequences_RemoveUnvisitedDuplicates (methods); + #endregion + } + } + + static void TransformSequences_Initialize (ReadOnlyCollection methods) + { + foreach (var method in methods) { + #region Cleanup + // remove nulls + if (method.SequencePoints == null) + method.SequencePoints = emptySeqPoints; + if (method.BranchPoints == null) + method.BranchPoints = emptyBranchPoints; + // No sequences in method, but branches present? => remove branches + if (method.SequencePoints.Length == 0 && method.BranchPoints.Length != 0) { + method.BranchPoints = emptyBranchPoints; + } + #endregion + } + } + + static void TransformSequences_AddSources (Module module, ReadOnlyCollection methods, IDictionary sourceRepository) + { + // Dictionary with stored source file names per module + var filesDictionary = new Dictionary(); + + foreach (var file in (module.Files ?? new File[0]). + Where (file => !String.IsNullOrWhiteSpace(file.FullPath) + && !filesDictionary.ContainsKey(file.FullPath))) + { + var source = CodeCoverageStringTextSource.GetSource(file.FullPath); + if (source != null) sourceRepository.Add (file.UniqueId, source); + filesDictionary.Add(file.FullPath, file.UniqueId); + } + + foreach (var method in methods) { + #region Add file references + if (method.SequencePoints.Length != 0) + MapFileReferences(method.SequencePoints, filesDictionary); + if (method.BranchPoints.Length != 0) + MapFileReferences(method.BranchPoints, filesDictionary); + #endregion + } + } + + static void TransformSequences_JoinWithBranches (ReadOnlyCollection methods) + { + foreach (var method in methods) { + #region Join BranchPoints children to SequencePoint parent + if (method.SequencePoints.Length != 0 && method.BranchPoints.Length != 0) { + // Quick match branches to sequence using SP&BP sort order by IL offset + // SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset + // ATTN: Sorted again to prevent future bugs if order of SP & BP is changed! + method.SequencePoints = method.SequencePoints.OrderBy(sp => sp.Offset).ToArray(); + method.BranchPoints = method.BranchPoints.OrderBy(bp => bp.Offset).ToArray(); + // Use stack because Stack.Pop is constant time + var branchStack = new Stack(method.BranchPoints); + // Join offset matching BranchPoints with SequencePoint "parent" + // Exclude all branches where BranchPoint.Offset < first method.SequencePoints.Offset + // Reverse() starts loop from highest offset to lowest + foreach (SequencePoint spParent in method.SequencePoints.Reverse()) { + // create branchPoints "child" list + spParent.BranchPoints = new List(); + // if BranchPoint.Offset is >= SequencePoint.Offset + // then move BranchPoint from stack to "child" list (Pop/Add) + while (branchStack.Count != 0 && branchStack.Peek().Offset >= spParent.Offset) { + spParent.BranchPoints.Add(branchStack.Pop()); + } + } + // clear the stack + branchStack.Clear(); + } + #endregion + } + } + + static void TransformSequences_RemoveBranchesOutOfOffset (ReadOnlyCollection methods, SourceRepository sourceRepository) + { + foreach (var method in methods) { + #region Use Offset To Remove Compiler Generated Branches + if (method.FileRef != null) { + long startOffset = long.MinValue; + long finalOffset = long.MaxValue; + CodeCoverageStringTextSource source = sourceRepository.getCodeCoverageStringTextSource(method.FileRef.UniqueId); + if (source != null && source.FileType == FileType.CSharp) { + var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp => sp.StartLine).ThenBy(sp => sp.StartColumn).Where(sp => sp.FileId == method.FileRef.UniqueId).ToArray(); + if (sourceLineOrderedSps.Length >= 2) { + // leftBrace.sp, any.sp, rightBrace.sp || method.sp; leftBrace.sp, rightBrace.sp + // method { + if (method.MethodPoint == sourceLineOrderedSps[0] && sourceRepository.isLeftBraceSequencePoint(sourceLineOrderedSps[1])) { + startOffset = sourceLineOrderedSps[1].Offset; + //sourceLineOrderedSps[1].BranchPoints = emptyBranchList; + } + // getter/setter/static-method { + else if (sourceRepository.isLeftBraceSequencePoint(sourceLineOrderedSps[0])) { + startOffset = sourceLineOrderedSps[0].Offset; + //sourceLineOrderedSps[0].BranchPoints = emptyBranchList; + } + if (sourceRepository.isRightBraceSequencePoint(sourceLineOrderedSps.Last())) { + finalOffset = sourceLineOrderedSps.Last().Offset; + } + } + } + if (startOffset != long.MinValue || finalOffset != long.MaxValue) { + // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset + // this will exclude "{" "}" compiler generated branches and ccrewrite Code Contract's + foreach (var sp in method.SequencePoints) { + if (sp != null && sp.BranchPoints != null && sp.BranchPoints.Count != 0 && sp.FileId == method.FileRef.UniqueId) { + if (sp.Offset <= startOffset || sp.Offset >= finalOffset) { + sp.BranchPoints = emptyBranchList; + } + } + } + } + } + #endregion + } + } + + static void TransformSequences_NormalizeBranches (ReadOnlyCollection methods) + { + foreach (var method in methods) { + #region Merge Branch-Exits for each Sequence + // Collection of validBranchPoints (child/connected to parent SequencePoint) + var validBranchPoints = new List(); + var branchExits = new Dictionary(); + foreach (var sp in method.SequencePoints) { + // SequencePoint has branches attached? + if (sp.BranchPoints != null && sp.BranchPoints.Count != 0) { + // Merge sp.BranchPoints using EndOffset as branchExits key + branchExits.Clear(); + foreach (var branchPoint in sp.BranchPoints) { + if (!branchExits.ContainsKey(branchPoint.EndOffset)) { + branchExits[branchPoint.EndOffset] = branchPoint; + // insert branch + } else { + branchExits[branchPoint.EndOffset].VisitCount += branchPoint.VisitCount; + // update branch + } + } + // Update SequencePoint counters + sp.BranchExitsCount = 0; + sp.BranchExitsVisit = 0; + foreach (var branchPoint in branchExits.Values) { + sp.BranchExitsCount += 1; + sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1; + } + // Add to validBranchPoints + validBranchPoints.AddRange(sp.BranchPoints); + sp.BranchPoints = emptyBranchList; + // clear + } + } + // Replace original method branchPoints with valid (filtered and joined) branches. + // Order is Required by FilePersistanceTest because it does not sets .Offset. + // (Order by UniqueSequencePoint is equal to order by .Offset when .Offset is set) + method.BranchPoints = validBranchPoints.OrderBy(bp => bp.UniqueSequencePoint).ToArray(); + #endregion + } + } + + static void TransformSequences_RemoveUnvisitedDuplicates (ReadOnlyCollection methods) + { + #region ToDo + /* Problems: + * 1) Compiler can duplicate sequence point (found in DBCL project) + * Solution: + * Remove unvisited duplicate? + * + * 2) Compiler can move SequencePoint into compiler generated method + * Solution? + * Identify compiler generated methods + * Match each with user method + * Move SequencePoints & branches into user method + * + */ + #endregion + + #region Examples + /* Duplicate SequencePoint Example + Generated Method * + * + * 100663434 + <_SetItems>b__b * System.Boolean DD.Collections.BitSetArray::<_SetItems>b__b(System.Int32) + * + * + Duplicate SP! * + * + * + * + * + * + Generated Method * + * + * 100663435 + <_SetItems>b__b_0* System.Boolean DD.Collections.BitSetArray::BitSetArray_<_SetItems>b__b_0(System.Int32) + * + * + Duplicate SP! * + * + * + * + * + * + User Method * + * + * 100663375 + * System.Void DD.Collections.BitSetArray::_SetItems(System.Collections.Generic.IEnumerable`1<System.Int32>) + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + #endregion + + var generatedMethods = new List(); + var userCodedMethods = new List(); + var lostSequencePoints = new Dictionary(); + //ILog TempLogger = LogManager.GetLogger("OpenCover"); + // Extract from generated methods (sp.BranchPoints are collected&connected) + foreach (var method in @methods) { + if (method.SequencePoints.Length != 0) { + if (method.isGenerated) { + //TempLogger.Info(getMethodName(method)); + generatedMethods.Add(method); + foreach (var sp in method.SequencePoints) { + if (sp.VisitCount == 0) { + lostSequencePoints.Add(sp, method); + } + } + } else { + userCodedMethods.Add(method); + } + } + } + //TempLogger.Warn("lostSequencePoints.Count " + lostSequencePoints.Count); + if (lostSequencePoints.Count != 0) { + // Remove lost if is duplicate + foreach (var method in @methods) { + foreach (var sp in method.SequencePoints) { + if (lostSequencePoints.ContainsKey(sp)) { + var cleanSequencePoints = new List(); + foreach (var spGenerated in lostSequencePoints[sp].SequencePoints) { + if (!spGenerated.Equals(sp)) { + cleanSequencePoints.Add(spGenerated); + } else { + //TempLogger.Warn("Sequence skipped, line: " + spGenerated.StartLine); + } + } + lostSequencePoints[sp].SequencePoints = cleanSequencePoints.ToArray(); + } + } + } + } + } + + } // Class +} // Namespace diff --git a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs index c295906f3..c2051c3f5 100644 --- a/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs +++ b/main/OpenCover.Framework/Symbols/CecilSymbolManager.cs @@ -389,6 +389,7 @@ private void GetSequencePointsForToken(int token, List list) } } + private static Regex isMovenext = new Regex(@"\<[^\s|>]+\>\w__\w(\w)?::MoveNext\(\)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture); private void GetBranchPointsForToken(int token, List list) { var methodDefinition = GetMethodDefinition(token); @@ -399,7 +400,7 @@ private void GetBranchPointsForToken(int token, List list) var instructions = methodDefinition.SafeGetMethodBody().Instructions; // if method is a generated MoveNext skip first branch (could be a switch or a branch) - var skipFirstBranch = Regex.IsMatch(methodDefinition.FullName, @"\<.+\>d__\d+::MoveNext\(\)$"); + var skipFirstBranch = isMovenext.IsMatch(methodDefinition.FullName); foreach (var instruction in instructions.Where(instruction => instruction.OpCode.FlowControl == FlowControl.Cond_Branch)) { diff --git a/main/OpenCover.Framework/Utility/SourceRepository.cs b/main/OpenCover.Framework/Utility/SourceRepository.cs new file mode 100644 index 000000000..27f91b570 --- /dev/null +++ b/main/OpenCover.Framework/Utility/SourceRepository.cs @@ -0,0 +1,224 @@ +/* + * Created by SharpDevelop. + * User: ddur + * Date: 23.12.2015. + * Time: 14:17 + * + * Copyright https://github.com/ddur + * This source code is released under the MIT License; see the accompanying license file. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using OpenCover.Framework.Model; + +namespace OpenCover.Framework.Utility +{ + /// + /// Collection of CodeCoverageStringTextSources + /// + public class SourceRepository : IDictionary + { + private readonly IDictionary repo = new Dictionary(); + /// + /// + /// + public SourceRepository() + { + } + + private uint fileID_cache = 0; + private CodeCoverageStringTextSource textSource_cache = null; + + public CodeCoverageStringTextSource getCodeCoverageStringTextSource (uint fileId) { + CodeCoverageStringTextSource source = null; + if (fileId != 0) { + if (fileID_cache == fileId) { + source = textSource_cache; + } else { + this.TryGetValue (fileId, out source); + if (source != null) { + fileID_cache = fileId; + textSource_cache = source; + } + } + } + return source; + } + + /// + /// SequencePoint source-string if available, else empty string + /// + /// SequencePoint + /// string + public string getSequencePointText (SequencePoint sp) { + if (sp != null) { + CodeCoverageStringTextSource source = this.getCodeCoverageStringTextSource (sp.FileId); + return source != null ? source.GetText(sp) : ""; + } + return ""; + } + /// + /// True if SequencePoint source-string == "{" + /// + /// + /// + public bool isLeftBraceSequencePoint (SequencePoint sp) { + return sp.isSingleCharSequencePoint && this.getSequencePointText(sp) == "{"; + } + /// + /// True if SequencePoint source-string == "}" + /// + /// + /// + public bool isRightBraceSequencePoint (SequencePoint sp) { + return sp.isSingleCharSequencePoint && this.getSequencePointText(sp) == "}"; + } + + #region IDictionary implementation + /// + /// + /// + /// + /// + public bool ContainsKey(uint key) + { + return repo.ContainsKey(key); + } + /// + /// + /// + /// + /// + public void Add(uint key, CodeCoverageStringTextSource value) + { + repo.Add(key, value); + } + /// + /// + /// + /// + /// + public bool Remove(uint key) + { + return repo.Remove(key); + } + /// + /// + /// + /// + /// + /// + public bool TryGetValue(uint key, out CodeCoverageStringTextSource value) + { + return repo.TryGetValue(key, out value); + } + /// + /// + /// + public CodeCoverageStringTextSource this[uint key] { + get { + return repo[key]; + } + set { + repo[key] = value; + } + } + /// + /// + /// + public ICollection Keys { + get { + return repo.Keys; + } + } + /// + /// + /// + public ICollection Values { + get { + return repo.Values; + } + } + #endregion + + #region ICollection implementation + /// + /// + /// + /// + public void Add(KeyValuePair item) + { + repo.Add(item); + } + /// + /// + /// + public void Clear() + { + repo.Clear(); + } + /// + /// + /// + /// + /// + public bool Contains(KeyValuePair item) + { + return repo.Contains(item); + } + /// + /// + /// + /// + /// + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + repo.CopyTo(array, arrayIndex); + } + /// + /// + /// + /// + /// + public bool Remove(KeyValuePair item) + { + return repo.Remove(item); + } + /// + /// + /// + public int Count { + get { + return repo.Count; + } + } + /// + /// + /// + public bool IsReadOnly { + get { + return repo.IsReadOnly; + } + } + #endregion + + #region IEnumerable implementation + /// + /// + /// + /// + public IEnumerator> GetEnumerator() + { + return repo.GetEnumerator(); + } + #endregion + + #region IEnumerable implementation + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)repo).GetEnumerator(); + } + #endregion + } +} From db4d4634ddc409a3757e265a6864fdcfa4ca4e52 Mon Sep 17 00:00:00 2001 From: ddur Date: Wed, 23 Dec 2015 20:46:47 +0100 Subject: [PATCH 40/41] Disable problematic code --- .../Persistance/BasePersistance.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index dc1f6e225..ad016940d 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -156,16 +156,8 @@ public bool IsTracking(string modulePath) /// public virtual void Commit() { - //ILog TempLogger = LogManager.GetLogger("OpenCover"); - //TempLogger.Info("Checking Coverage Session..."); if (CoverageSession.Modules != null) { - //TempLogger.Info("MarkSkippedMethods..."); MarkSkippedMethods(); - //TempLogger.Info("TransformSequences..."); - TransformSequences(); - //TempLogger.Info("CalculateCoverage..."); - CalculateCoverage(); - //TempLogger.Info("FilterSkippedMethods..."); if (CommandLine.HideSkipped != null && CommandLine.HideSkipped.Any()) { foreach (var skippedMethod in CommandLine.HideSkipped.OrderBy(x => x)) { @@ -195,6 +187,8 @@ public virtual void Commit() } } } + TransformSequences(); + CalculateCoverage(); } } @@ -551,7 +545,7 @@ private void TransformSequences() { #endregion #region step 2: Transformations - TransformSequences_RemoveUnvisitedDuplicates (methods); + //TransformSequences_RemoveUnvisitedDuplicates (methods); #endregion } } From f63bc887db3a4fac1a87bb70ef123ae3872cb1d3 Mon Sep 17 00:00:00 2001 From: ddur Date: Wed, 23 Dec 2015 22:20:02 +0100 Subject: [PATCH 41/41] Enable Remove Unvisited SequencePoint Duplicates Fix null references --- .../Persistance/BasePersistance.cs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/main/OpenCover.Framework/Persistance/BasePersistance.cs b/main/OpenCover.Framework/Persistance/BasePersistance.cs index ad016940d..17be3a104 100644 --- a/main/OpenCover.Framework/Persistance/BasePersistance.cs +++ b/main/OpenCover.Framework/Persistance/BasePersistance.cs @@ -814,23 +814,23 @@ static void TransformSequences_RemoveUnvisitedDuplicates (ReadOnlyCollection(); - var userCodedMethods = new List(); + //var generatedMethods = new List(); + //var userCodedMethods = new List(); var lostSequencePoints = new Dictionary(); //ILog TempLogger = LogManager.GetLogger("OpenCover"); // Extract from generated methods (sp.BranchPoints are collected&connected) foreach (var method in @methods) { - if (method.SequencePoints.Length != 0) { + if (!Object.ReferenceEquals(method, null) && method.SequencePoints.Length != 0) { if (method.isGenerated) { //TempLogger.Info(getMethodName(method)); - generatedMethods.Add(method); + //generatedMethods.Add(method); foreach (var sp in method.SequencePoints) { - if (sp.VisitCount == 0) { + if (!Object.ReferenceEquals(sp, null) && sp.VisitCount == 0) { lostSequencePoints.Add(sp, method); } } } else { - userCodedMethods.Add(method); + //userCodedMethods.Add(method); } } } @@ -838,17 +838,19 @@ static void TransformSequences_RemoveUnvisitedDuplicates (ReadOnlyCollection(); - foreach (var spGenerated in lostSequencePoints[sp].SequencePoints) { - if (!spGenerated.Equals(sp)) { - cleanSequencePoints.Add(spGenerated); - } else { - //TempLogger.Warn("Sequence skipped, line: " + spGenerated.StartLine); + if (!Object.ReferenceEquals(method, null)) { + foreach (var sp in method.SequencePoints) { + if (!Object.ReferenceEquals(sp, null) && lostSequencePoints.ContainsKey(sp)) { + var cleanSequencePoints = new List(); + foreach (var spGenerated in lostSequencePoints[sp].SequencePoints) { + if (!spGenerated.Equals(sp)) { + cleanSequencePoints.Add(spGenerated); + } else { + //TempLogger.Warn("Sequence skipped, line: " + spGenerated.StartLine); + } } + lostSequencePoints[sp].SequencePoints = cleanSequencePoints.ToArray(); } - lostSequencePoints[sp].SequencePoints = cleanSequencePoints.ToArray(); } } }