diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp b/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp index 59317e30d1..757836693c 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp +++ b/src/Agent/NewRelic/Profiler/MethodRewriterTest/FunctionManipulatorTest.cpp @@ -35,6 +35,15 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentApi(); } + TEST_METHOD(instrument_api_method_netframework_inagentcache_ParameterlessWithObjectReturn) + { + auto function = std::make_shared(); + MakeFunctionParameterlessWithObjectReturnType(function); + ApiFunctionManipulator manipulator(function, std::make_shared(nullptr, _X("")), false, AgentCallStyle::Strategy::InAgentCache); + + manipulator.InstrumentApi(); + } + TEST_METHOD(instrument_api_method_netframework_appdomaincache) { auto function = std::make_shared(); @@ -43,6 +52,15 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentApi(); } + TEST_METHOD(instrument_api_method_netframework_appdomaincache_ParameterlessWithObjectReturn) + { + auto function = std::make_shared(); + MakeFunctionParameterlessWithObjectReturnType(function); + ApiFunctionManipulator manipulator(function, std::make_shared(nullptr, _X("")), false, AgentCallStyle::Strategy::AppDomainCache); + + manipulator.InstrumentApi(); + } + TEST_METHOD(instrument_api_method_netframework_reflection) { auto function = std::make_shared(); @@ -51,6 +69,15 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentApi(); } + TEST_METHOD(instrument_api_method_netframework_reflection_ParameterlessWithObjectReturn) + { + auto function = std::make_shared(); + MakeFunctionParameterlessWithObjectReturnType(function); + ApiFunctionManipulator manipulator(function, std::make_shared(nullptr, _X("")), false, AgentCallStyle::Strategy::Reflection); + + manipulator.InstrumentApi(); + } + TEST_METHOD(instrument_api_method_coreclr_inagentcache) { auto function = std::make_shared(); @@ -60,6 +87,16 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentApi(); } + TEST_METHOD(instrument_api_method_coreclr_inagentcache_ParameterlessWithObjectReturn) + { + auto function = std::make_shared(); + function->_isCoreClr = true; + MakeFunctionParameterlessWithObjectReturnType(function); + ApiFunctionManipulator manipulator(function, std::make_shared(nullptr, _X("")), true, AgentCallStyle::Strategy::InAgentCache); + + manipulator.InstrumentApi(); + } + TEST_METHOD(instrument_api_method_coreclr_appdomaincache) { auto function = std::make_shared(); @@ -69,6 +106,16 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentApi(); } + TEST_METHOD(instrument_api_method_coreclr_appdomaincache_ParameterlessWithObjectReturn) + { + auto function = std::make_shared(); + function->_isCoreClr = true; + MakeFunctionParameterlessWithObjectReturnType(function); + ApiFunctionManipulator manipulator(function, std::make_shared(nullptr, _X("")), true, AgentCallStyle::Strategy::AppDomainCache); + + manipulator.InstrumentApi(); + } + TEST_METHOD(instrument_api_method_coreclr_reflection) { auto function = std::make_shared(); @@ -78,6 +125,16 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentApi(); } + TEST_METHOD(instrument_api_method_coreclr_reflection_ParameterlessWithObjectReturn) + { + auto function = std::make_shared(); + function->_isCoreClr = true; + MakeFunctionParameterlessWithObjectReturnType(function); + ApiFunctionManipulator manipulator(function, std::make_shared(nullptr, _X("")), true, AgentCallStyle::Strategy::Reflection); + + manipulator.InstrumentApi(); + } + TEST_METHOD(instrument_minimal_method_netframework_inagentcache) { auto function = std::make_shared(); @@ -222,6 +279,45 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T manipulator.InstrumentHelper(); } + TEST_METHOD(helper_method_GetAgentShimFinishTracerDelegateFunc) + { + auto function = std::make_shared(); + function->_functionName = _X("GetAgentShimFinishTracerDelegateFunc"); + HelperFunctionManipulator manipulator(function, true, AgentCallStyle::Strategy::InAgentCache); + + manipulator.InstrumentHelper(); + } + + TEST_METHOD(helper_method_StoreAgentMethodInvokerFunc) + { + auto function = std::make_shared(); + function->_functionName = _X("StoreAgentMethodInvokerFunc"); + HelperFunctionManipulator manipulator(function, true, AgentCallStyle::Strategy::InAgentCache); + + manipulator.InstrumentHelper(); + } + + TEST_METHOD(helper_method_StoreAgentShimFinishTracerDelegateFunc) + { + auto function = std::make_shared(); + function->_functionName = _X("StoreAgentShimFinishTracerDelegateFunc"); + HelperFunctionManipulator manipulator(function, true, AgentCallStyle::Strategy::InAgentCache); + + manipulator.InstrumentHelper(); + } + + TEST_METHOD(functionManipulator_ThrowsWhenLoadMethodInfoCalledWithUnsupportedCallStrategy) + { + std::function test = []() { + auto function = std::make_shared(); + TestFunctionManipulator manipulator(function, true, AgentCallStyle::Strategy::InAgentCache); + + manipulator.TestLoadMethodInfo(_X(""), _X(""), _X(""), function->GetFunctionId(), []() {}); + }; + + Assert::ExpectException(test, _X("Should throw exception for unsupported agent call style.")); + } + //TEST_METHOD(test_method_with_no_code) //{ // Assert::Fail(L"Test not implemented."); @@ -326,5 +422,28 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T instrumentationPoint->MethodName = function->GetFunctionName(); return instrumentationPoint; } + + void MakeFunctionParameterlessWithObjectReturnType(std::shared_ptr& function) + { + function->_signature->clear(); + function->_signature->push_back(0x00); // default calling convention + function->_signature->push_back(0x00); // 0 params + function->_signature->push_back(0x1c); // object return + } + + class TestFunctionManipulator : FunctionManipulator + { + public: + TestFunctionManipulator(IFunctionPtr function, const bool isCoreClr, const AgentCallStyle::Strategy agentCallStrategy) : + FunctionManipulator(function, isCoreClr, agentCallStrategy) + { + Initialize(); + } + + void TestLoadMethodInfo(xstring_t assemblyPath, xstring_t className, xstring_t methodName, uintptr_t functionId, std::function argumentTypesLambda) + { + LoadMethodInfo(assemblyPath, className, methodName, functionId, argumentTypesLambda); + } + }; }; }}}} diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/InstrumentorsTest.cpp b/src/Agent/NewRelic/Profiler/MethodRewriterTest/InstrumentorsTest.cpp index 18ab663bc3..bc54d74f8e 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/InstrumentorsTest.cpp +++ b/src/Agent/NewRelic/Profiler/MethodRewriterTest/InstrumentorsTest.cpp @@ -321,11 +321,26 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T AssertHelperMethodIsInstrumented(true, _X("InvokeAgentMethodInvokerFunc")); } + TEST_METHOD(HelperInstrumentor_CoreClr_ShouldInstrument_GetAgentShimFinishTracerDelegateFunc) + { + AssertHelperMethodIsInstrumented(true, _X("GetAgentShimFinishTracerDelegateFunc")); + } + TEST_METHOD(HelperInstrumentor_CoreClr_ShouldInstrument_GetAgentMethodInvokerObject) { AssertHelperMethodIsInstrumented(true, _X("GetAgentMethodInvokerObject")); } + TEST_METHOD(HelperInstrumentor_CoreClr_ShouldInstrument_StoreAgentMethodInvokerFunc) + { + AssertHelperMethodIsInstrumented(true, _X("StoreAgentMethodInvokerFunc")); + } + + TEST_METHOD(HelperInstrumentor_CoreClr_ShouldInstrument_StoreAgentShimFinishTracerDelegateFunc) + { + AssertHelperMethodIsInstrumented(true, _X("StoreAgentShimFinishTracerDelegateFunc")); + } + TEST_METHOD(HelperInstrumentor_CoreClr_ShouldInstrument_EnsureInitialized) { AssertHelperMethodIsInstrumented(true, _X("EnsureInitialized")); @@ -386,11 +401,26 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T AssertHelperMethodIsInstrumented(false, _X("InvokeAgentMethodInvokerFunc")); } + TEST_METHOD(HelperInstrumentor_NetFramework_ShouldInstrument_GetAgentShimFinishTracerDelegateFunc) + { + AssertHelperMethodIsInstrumented(false, _X("GetAgentShimFinishTracerDelegateFunc")); + } + TEST_METHOD(HelperInstrumentor_NetFramework_ShouldInstrument_GetAgentMethodInvokerObject) { AssertHelperMethodIsInstrumented(false, _X("GetAgentMethodInvokerObject")); } + TEST_METHOD(HelperInstrumentor_NetFramework_ShouldInstrument_StoreAgentMethodInvokerFunc) + { + AssertHelperMethodIsInstrumented(false, _X("StoreAgentMethodInvokerFunc")); + } + + TEST_METHOD(HelperInstrumentor_NetFramework_ShouldInstrument_StoreAgentShimFinishTracerDelegateFunc) + { + AssertHelperMethodIsInstrumented(false, _X("StoreAgentShimFinishTracerDelegateFunc")); + } + TEST_METHOD(HelperInstrumentor_NetFramework_ShouldInstrument_EnsureInitialized) { AssertHelperMethodIsInstrumented(false, _X("EnsureInitialized")); diff --git a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp index 959c41555d..1254cf1153 100644 --- a/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp +++ b/src/Agent/NewRelic/Profiler/MethodRewriterTest/MethodRewriterTest.cpp @@ -309,6 +309,33 @@ namespace NewRelic { namespace Profiler { namespace MethodRewriter { namespace T Assert::IsTrue(methodRewriter->ShouldInstrumentFunction(_X("GetAgentMethodInvokerObject"))); } + TEST_METHOD(ShouldInstrumentFunction_StoreAgentMethodInvokerObject) + { + auto function = std::make_shared(); + + auto methodRewriter = GetMethodRewriterWithConfigurationForFunction(function); + + Assert::IsTrue(methodRewriter->ShouldInstrumentFunction(_X("StoreAgentMethodInvokerObject"))); + } + + TEST_METHOD(ShouldInstrumentFunction_StoreAgentShimFinishTracerDelegateFunc) + { + auto function = std::make_shared(); + + auto methodRewriter = GetMethodRewriterWithConfigurationForFunction(function); + + Assert::IsTrue(methodRewriter->ShouldInstrumentFunction(_X("StoreAgentShimFinishTracerDelegateFunc"))); + } + + TEST_METHOD(ShouldInstrumentFunction_GetAgentShimFinishTracerDelegateFunc) + { + auto function = std::make_shared(); + + auto methodRewriter = GetMethodRewriterWithConfigurationForFunction(function); + + Assert::IsTrue(methodRewriter->ShouldInstrumentFunction(_X("GetAgentShimFinishTracerDelegateFunc"))); + } + private: Configuration::InstrumentationConfigurationPtr GetInstrumentationConfigurationForFunction(std::shared_ptr function) {