504 lines
18 KiB
C++
504 lines
18 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#include "tests/common/helpers.h"
|
|
#include "tests/common/badEvents.h"
|
|
#include "tests/config.h"
|
|
#include "tests/fixture/memoryCheckFixture.h"
|
|
#include <../private/ubiservices/core/chrono/chronometer.h>
|
|
#include <../private/ubiservices/core/helpers/instancesManager.h>
|
|
#include <ubiservices/core/log/outputFormat.h>
|
|
#include <ubiservices/core/log/eventLog.h>
|
|
#include <ubiservices/loggingHelper.h>
|
|
#include <ubiservices/ubiservices.h>
|
|
#include <ubiservices/services/authentication/authenticationClient.h>
|
|
#include <ubiservices/services/authentication/authenticationNotification.h>
|
|
#if defined(US_SDK_S2S)
|
|
#include "ubiservices/services/event/types/eventTypeInfo.h"
|
|
#endif
|
|
#include <ubiservices/services/notification/connectionInfoOwn.h>
|
|
#include <ubiservices/services/notification/notificationClient.h>
|
|
#include <../private/ubiservices/services/preflightEndpoint.h>
|
|
#include <external/harbourcommon/libraries/harboureal/implementation/simplemem.h>
|
|
#include <usCommon/options.h>
|
|
#include <usCommon/settings.h>
|
|
#if defined(US_SDK_S2S)
|
|
#include <usCommon/authenticationHelper.h>
|
|
#endif
|
|
|
|
#if defined(US_PROFILE)
|
|
#include <ealfile.h>
|
|
#include <ealnet.h>
|
|
#include <faprofiler.h>
|
|
#include <faprofiler_disk.h>
|
|
#include <faprofiler_network.h>
|
|
#include <ubiservices/core/profiler/profilerMacros.h>
|
|
|
|
#define FAPROFILER_ALLOCATED_MEMORY 16*1024*1024
|
|
#define FAPROFILER_FILE_NAME "UbiservicesProfile"
|
|
#endif
|
|
|
|
#if defined(US_TARGET_XONE)
|
|
#include <ubiservices/core/log/logDevice.h>
|
|
#include <usCommon/win32/firstPartyInit.h>
|
|
|
|
namespace harbour_printf //ubiservices_hack
|
|
{
|
|
int internalVPrintf(const char* format, va_list& argList);
|
|
int internalPrintf(const char* format, ...);
|
|
};
|
|
|
|
#elif defined(US_TARGET_SWITCH)
|
|
#include "usCommon/nnx/firstPartyInit.h"
|
|
#elif defined(US_TARGET_PS4)
|
|
#include "usCommon/ps4/firstPartyInit.h"
|
|
#elif defined(US_TARGET_KILI)
|
|
#include "usCommon/kili/firstPartyInit.h"
|
|
#elif defined(US_TARGET_GGP)
|
|
#include "usCommon/ggp/firstPartyInit.h"
|
|
#elif defined(US_TARGET_SWITCH)
|
|
#define NintendoApplicationIdForUbiservices "01009d800a1d0000"
|
|
#endif
|
|
|
|
namespace US_NS {;
|
|
|
|
#if defined(US_USE_LIBCURL) && !defined(US_DLL)
|
|
extern bool g_skipEalMemForLibcurl;
|
|
#endif
|
|
|
|
extern US_DLL_API EventLog* g_testEventLog; // Only needed for test purposes
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
namespace LeakChecker_BF
|
|
{
|
|
Vector<EventTypeInfo> getDefaultEventTypesForSaveGame()
|
|
{
|
|
US_TEST_STATIC_ASSERT(static_cast<uint32>(EventType::ENUM_END) == 18u, "getDefaultEventTypesForSaveGame() needs to be updated");
|
|
|
|
// Default config accepts all event types (Note : This would be a wrong integration in games)
|
|
return Vector<EventTypeInfo>
|
|
{
|
|
EventTypeInfo(EventType::PlayerAchievement),
|
|
EventTypeInfo(EventType::GameStart),
|
|
EventTypeInfo(EventType::GameSuspendedStart),
|
|
EventTypeInfo(EventType::GameSuspendedStop),
|
|
EventTypeInfo(EventType::PlayerStart),
|
|
EventTypeInfo(EventType::ContextStart, "myContextType0"),
|
|
EventTypeInfo(EventType::ContextStart, "myContextType1"),
|
|
EventTypeInfo(EventType::ContextStart, "myContextType2"),
|
|
EventTypeInfo(EventType::ContextStart, "myContextType3"),
|
|
EventTypeInfo(EventType::ContextStop, "myContextType0"),
|
|
EventTypeInfo(EventType::ContextStop, "myContextType1"),
|
|
EventTypeInfo(EventType::ContextStop, "myContextType2"),
|
|
EventTypeInfo(EventType::ContextStop, "myContextType3"),
|
|
EventTypeInfo(EventType::GameLocalization),
|
|
EventTypeInfo(EventType::HardwareSpecs),
|
|
EventTypeInfo(EventType::PlayerProgression, "Mission"),
|
|
EventTypeInfo(EventType::PlayerProgression, "myProgression"),
|
|
EventTypeInfo(EventType::PlayerPosition),
|
|
EventTypeInfo(EventType::PlayerPrimaryStore),
|
|
EventTypeInfo(EventType::PlayerNewsAction),
|
|
EventTypeInfo(EventType::PlayerNewsImpression),
|
|
EventTypeInfo(EventType::PlayerStatsPlayTime),
|
|
EventTypeInfo(EventType::Custom, CUSTOM_EVENT_NAME),
|
|
EventTypeInfo(EventType::Service, TestHelpers_BF::SERVICE_EVENT_NAME),
|
|
EventTypeInfo(EventType::Service, "TestingService"),
|
|
};
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
::testing::AssertionResult WebsocketHelper::waitForWebsocketInit(Facade& facade)
|
|
{
|
|
class Condition : public US_TEST_NS::Helper::ConditionTemplate
|
|
{
|
|
public:
|
|
Condition(Facade& facade)
|
|
: m_facade(facade)
|
|
, m_listener(facade.getAuthenticationClient().createNotificationListener())
|
|
{
|
|
}
|
|
|
|
bool operator()() const
|
|
{
|
|
return (m_facade.getNotificationClient().isConnectionActive() && !m_facade.getNotificationClient().getOwnConnectionInfo().m_contactUrl.isEmpty());
|
|
}
|
|
|
|
private:
|
|
//US_CLASS_COPY_NOT_ALLOWED(Condition)
|
|
Condition(const Condition& dummy) : m_facade(dummy.m_facade) {}
|
|
Condition& operator=(Condition&) { return *this; }
|
|
Facade& m_facade;
|
|
mutable ListenerHandler<AuthenticationNotification> m_listener;
|
|
} condition(facade);
|
|
|
|
return US_TEST_NS::Helper::WaitFor(condition, 1ull, 10*1000ull, "websocket init")
|
|
? ::testing::AssertionSuccess()
|
|
: ::testing::AssertionFailure() << "Timed out waiting for connection to be active";
|
|
}
|
|
#endif
|
|
|
|
#if !defined(US_RETAIL)
|
|
extern bool US_DLL_API s_forceNonSecure;
|
|
extern bool US_DLL_API g_forcePreflightURL[7];
|
|
#endif
|
|
|
|
LeakChecker::LeakChecker(FixtureType type)
|
|
: m_mightLeak(false)
|
|
, m_willLeak(false)
|
|
, m_type(type)
|
|
, m_skipEalMemForLibcurl(false)
|
|
#if defined(US_ENABLE_ALLOC_STATS)
|
|
, m_currentTestAllocStatistics(g_stats)
|
|
#endif
|
|
{
|
|
#if !defined(US_RETAIL)
|
|
s_forceNonSecure = NS_COMMON::Options::forceUnsecure();
|
|
g_forcePreflightURL[PreflightEndpoint::Applications] = NS_COMMON::Options::preflightURL(PreflightEndpoint::Applications);
|
|
g_forcePreflightURL[PreflightEndpoint::Users] = NS_COMMON::Options::preflightURL(PreflightEndpoint::Users);
|
|
g_forcePreflightURL[PreflightEndpoint::Policies] = NS_COMMON::Options::preflightURL(PreflightEndpoint::Policies);
|
|
g_forcePreflightURL[PreflightEndpoint::ProfilesExternal] = NS_COMMON::Options::preflightURL(PreflightEndpoint::ProfilesExternal);
|
|
g_forcePreflightURL[PreflightEndpoint::Sessions] = NS_COMMON::Options::preflightURL(PreflightEndpoint::Sessions);
|
|
#endif
|
|
}
|
|
|
|
LeakChecker::~LeakChecker()
|
|
{
|
|
#if !defined(US_RETAIL)
|
|
s_forceNonSecure = false;
|
|
#endif
|
|
}
|
|
|
|
void LeakChecker::SetUp()
|
|
{
|
|
#if defined(US_USE_LIBCURL) && !defined(US_DLL) && !defined(US_TARGET_SWITCH)
|
|
g_skipEalMemForLibcurl = m_skipEalMemForLibcurl;
|
|
#endif
|
|
|
|
BadEvents::createInstance();
|
|
|
|
// Wait at least 1 ms to make sure that all subsequent memory allocations
|
|
// will not have the same timer value than m_testStartTime. Otherwise
|
|
// getAllocatedMemoryInfo would not display those allocations.
|
|
Helper::sleep(1);
|
|
|
|
#if defined(US_PROFILE)
|
|
FAProfiler::Init(FAPROFILER_ALLOCATED_MEMORY);
|
|
FAProfilerDisk::Init();
|
|
FAProfiler::Enable();
|
|
EalPerfLibInit();
|
|
|
|
// This fake a frame for the whole test
|
|
// Not required but it can be helpful
|
|
FAProfiler::BeginNewFrame();
|
|
#endif
|
|
|
|
US_PERF_SET_CURRENT_THREADNAME("Main");
|
|
if (m_type == AutoExecuteInit || m_type == InitNoScheduler)
|
|
{
|
|
initDefaultSDK();
|
|
}
|
|
|
|
if (m_type == AutoExecuteInit)
|
|
{
|
|
resetLogLevel();
|
|
|
|
#if defined(US_TARGET_XONE)
|
|
// The following internal device allows to redirect UbiServices internal
|
|
// logging into the Google test logging framework. This may be useful
|
|
// to redirect all the logging sequence into a single output file.
|
|
// This solution however does not work for unit tests explicitly
|
|
// initializing the SDK.
|
|
|
|
class LogDeviceGtest : public LogDevice
|
|
{
|
|
public:
|
|
void output(const String& logString, LogLevel logLevel, const String& file, uint32 line) override
|
|
{
|
|
US_UNUSED(logLevel);
|
|
US_UNUSED(file);
|
|
US_UNUSED(line);
|
|
|
|
harbour_printf::internalPrintf("%s", logString.getUtf8());
|
|
}
|
|
};
|
|
|
|
InstancesManager::getInstance()->getEventLog().setLogDevice(US_NEW(LogDeviceGtest));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void LeakChecker::TearDown()
|
|
{
|
|
if (m_type == AutoExecuteInit || m_type == InitNoScheduler)
|
|
{
|
|
uninitDefaultSDK();
|
|
}
|
|
|
|
EXPECT_TRUE(!m_willLeak || SIMPL_NS::g_memoryLeakAtShutdown) <<
|
|
"[ US_TEST_ERROR_FAILED ] Expected memory leaks did not occurred in this test.";
|
|
EXPECT_TRUE(m_willLeak || m_mightLeak || !SIMPL_NS::g_memoryLeakAtShutdown) <<
|
|
"[ US_TEST_ERROR_FAILED ] Memory leaks occurred during this test.";
|
|
EXPECT_FALSE(SIMPL_NS::g_memoryCorruption) <<
|
|
"[ US_TEST_ERROR_FAILED ] Memory Corruption occurred during this test.";
|
|
|
|
#if defined(US_PROFILE)
|
|
// Profiler needs to be terminated after Ubiservices or it might crash during unitiliazeSDK()
|
|
EalPerfLibShutdown();
|
|
FAProfiler::Disable();
|
|
FAProfilerDisk::Serialize(getTestName());
|
|
FAProfilerDisk::Shutdown();
|
|
FAProfiler::Shutdown();
|
|
#endif
|
|
|
|
#if defined(US_ENABLE_ALLOC_STATS)
|
|
{
|
|
m_currentTestAllocStatistics.m_allocCountCurrent = g_stats.m_allocCountCurrent - m_currentTestAllocStatistics.m_allocCountCurrent;
|
|
m_currentTestAllocStatistics.m_allocCountTotal = g_stats.m_allocCountTotal - m_currentTestAllocStatistics.m_allocCountTotal;
|
|
m_currentTestAllocStatistics.m_allocSizeTotal = g_stats.m_allocSizeTotal - m_currentTestAllocStatistics.m_allocSizeTotal;
|
|
|
|
m_currentTestAllocStatistics.m_allocArrayCountCurrent = g_stats.m_allocArrayCountCurrent - m_currentTestAllocStatistics.m_allocArrayCountCurrent;
|
|
m_currentTestAllocStatistics.m_allocArrayCountTotal = g_stats.m_allocArrayCountTotal - m_currentTestAllocStatistics.m_allocArrayCountTotal;
|
|
m_currentTestAllocStatistics.m_allocArraySizeTotal = g_stats.m_allocArraySizeTotal - m_currentTestAllocStatistics.m_allocArraySizeTotal;
|
|
|
|
m_currentTestAllocStatistics.m_newArrayWithZero = g_stats.m_newArrayWithZero - m_currentTestAllocStatistics.m_newArrayWithZero;
|
|
m_currentTestAllocStatistics.m_deleteWithNull = g_stats.m_deleteWithNull - m_currentTestAllocStatistics.m_deleteWithNull;
|
|
m_currentTestAllocStatistics.m_deleteArrayWithNull = g_stats.m_deleteArrayWithNull - m_currentTestAllocStatistics.m_deleteArrayWithNull;
|
|
}
|
|
|
|
// Printing with tabs for easier adaptation to excel sheet
|
|
US_NS::Log::print("\n");
|
|
US_NS::Log::print("--- Memory allocation statistics ---\n");
|
|
US_NS::Log::print("Stats: Test_name\tallocCountCurrent\tallocCountTotal\tallocSizeTotal\tallocArrayCountCurrent\t");
|
|
US_NS::Log::print("allocArrayCountTotal\tallocArraySizeTotal\tnewArrayWithZero\tdeleteWithNull\tdeleteArrayWithNull\n");
|
|
US_NS::Log::print("Stats: %s.%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", getTestCaseName(), getTestName(), m_currentTestAllocStatistics.m_allocCountCurrent
|
|
, m_currentTestAllocStatistics.m_allocCountTotal, m_currentTestAllocStatistics.m_allocSizeTotal, m_currentTestAllocStatistics.m_allocArrayCountCurrent
|
|
, m_currentTestAllocStatistics.m_allocArrayCountTotal, m_currentTestAllocStatistics.m_allocArraySizeTotal, m_currentTestAllocStatistics.m_newArrayWithZero
|
|
, m_currentTestAllocStatistics.m_deleteWithNull, m_currentTestAllocStatistics.m_deleteArrayWithNull);
|
|
US_NS::Log::print("-----------------------------------\n");
|
|
#endif
|
|
|
|
// NB : This line needs to be placed AFTER the EalPerfLisShutdown in the US_PROFILE part.
|
|
EXPECT_TRUE(g_AllocCounter == NULL) <<
|
|
"[ US_TEST_ERROR_FAILED ] Memory manager shouldn't be initialized anymore at the end of the test. "
|
|
"Please check in this test that the number of SDK initialize matches the number of SDK uninitialize";
|
|
|
|
BadEvents::deleteInstance();
|
|
|
|
#if defined(US_USE_LIBCURL) && !defined(US_DLL) && !defined(US_TARGET_SWITCH)
|
|
g_skipEalMemForLibcurl = false;
|
|
#endif
|
|
}
|
|
|
|
FacadeInternal& LeakChecker::getFacadeInternal(Facade& facade)
|
|
{
|
|
return *facade.m_facadeInternal;
|
|
}
|
|
|
|
const FacadeInternal& LeakChecker::getFacadeInternal(const Facade& facade)
|
|
{
|
|
return *facade.m_facadeInternal;
|
|
}
|
|
|
|
EventLog* LeakChecker::getEventLog()
|
|
{
|
|
if (g_testEventLog == NULL)
|
|
{
|
|
g_testEventLog = US_NEW(EventLog);
|
|
}
|
|
return g_testEventLog;
|
|
}
|
|
|
|
void LeakChecker::outputLog(LogLevel level, LogCategory category, const char* string, const char* file, uint32 line)
|
|
{
|
|
if (g_testEventLog == NULL)
|
|
{
|
|
g_testEventLog = US_NEW(EventLog);
|
|
}
|
|
|
|
if (g_testEventLog->isLogEnabled(level, category))
|
|
{
|
|
g_testEventLog->outputLog(level, category, string, file, line);
|
|
}
|
|
}
|
|
|
|
void LeakChecker::setLogLevel(LogLevel logLevel)
|
|
{
|
|
if (g_testEventLog == NULL)
|
|
{
|
|
g_testEventLog = US_NEW(EventLog);
|
|
}
|
|
|
|
g_testEventLog->setLogLevel(logLevel);
|
|
g_testEventLog->getOutputFormat().setShowTag(OutputFormat::Time, true);
|
|
|
|
// Forces level to warning in case the previously executed test set it to an other value.
|
|
if(InstancesManager::getInstance() != NULL)
|
|
{
|
|
EventLog& eventLog = InstancesManager::getInstance()->getEventLog();
|
|
eventLog.setLogLevel(logLevel);
|
|
}
|
|
}
|
|
|
|
void LeakChecker::resetLogLevel()
|
|
{
|
|
setLogLevel(LogLevel::Warning);
|
|
}
|
|
|
|
void LeakChecker::setMultiLinesLog(bool state)
|
|
{
|
|
if (g_testEventLog == NULL)
|
|
{
|
|
g_testEventLog = US_NEW(EventLog);
|
|
}
|
|
|
|
g_testEventLog->enableMultiLines(state); // Setup for US_TEST_LOG EventLog
|
|
|
|
#if defined(US_LOG_ENABLED)
|
|
LoggingHelper::enableMultiLines(state); // Setup for US_LOG EventLog
|
|
#endif
|
|
}
|
|
|
|
void LeakChecker::setupDebugLogging()
|
|
{
|
|
#if defined(US_LOG_ENABLED)
|
|
LoggingHelper::enableMultiLines(true);
|
|
LoggingHelper::enableVerbose(true);
|
|
#endif
|
|
setLogLevel(LogLevel::Debug);
|
|
}
|
|
|
|
void LeakChecker::disableLogCategories()
|
|
{
|
|
#if defined(US_LOG_ENABLED)
|
|
|
|
for (uint32 i = static_cast<uint32>(LogCategory::ENUM_BEGIN); i != static_cast<uint32>(LogCategory::ENUM_END); ++i)
|
|
{
|
|
LoggingHelper::disableCategory(static_cast<LogCategory>(i));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void LeakChecker::enableLogCategories(const Vector<LogCategory>& categories)
|
|
{
|
|
#if defined(US_LOG_ENABLED)
|
|
disableLogCategories();
|
|
for (LogCategory category : categories)
|
|
{
|
|
LoggingHelper::enableCategory(category);
|
|
}
|
|
#else
|
|
US_UNUSED(categories);
|
|
#endif
|
|
}
|
|
|
|
HttpConfig LeakChecker::getHttpConfig() const
|
|
{
|
|
return HttpConfig();
|
|
}
|
|
|
|
const char* LeakChecker::getTestName() const
|
|
{
|
|
const ::testing::TestInfo* testInfo = ::testing::UnitTest::GetInstance()->current_test_info();
|
|
return testInfo->name();
|
|
}
|
|
|
|
const char* US_NS::LeakChecker::getTestCaseName() const
|
|
{
|
|
const ::testing::TestInfo* testInfo = ::testing::UnitTest::GetInstance()->current_test_info();
|
|
return testInfo->test_case_name();
|
|
}
|
|
|
|
void LeakChecker::initDefaultSDK()
|
|
{
|
|
initializeSdk();
|
|
|
|
if (m_type != InitNoScheduler)
|
|
{
|
|
#if defined(ENABLE_PROXY_SETTINGS_TEST)
|
|
US_NS::HttpConfig httpConfig;
|
|
|
|
httpConfig.m_proxy.m_host = "127.0.0.1"; // Fiddler proxy port
|
|
httpConfig.m_proxy.m_port = 8888; // Fiddler proxy port
|
|
httpConfig.m_proxy.m_username = "username";
|
|
httpConfig.m_proxy.m_username = "password";
|
|
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::Enabled;
|
|
#elif defined(US_TARGET_SWITCH)
|
|
US_NS::HttpConfig httpConfig;
|
|
|
|
//httpConfig.m_proxy.m_host = "127.0.0.1"; // Fiddler proxy port
|
|
//httpConfig.m_proxy.m_port = 8888; // Fiddler proxy port
|
|
//httpConfig.m_proxy.m_username = "username";
|
|
//httpConfig.m_proxy.m_username = "password";
|
|
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::AutoProxy;
|
|
#else
|
|
const US_NS::HttpConfig httpConfig = getHttpConfig();
|
|
#endif
|
|
const GameConfig gameConfig(ApplicationId(NS_COMMON::Options::getApplicationId().c_str())
|
|
#if defined(US_SDK_TEST_CHINA)
|
|
, String("CHINA_IS_PROD")
|
|
#else
|
|
, NS_COMMON::Options::getApplicationBuildId().c_str()
|
|
#endif
|
|
#if defined(US_SDK_S2S)
|
|
, NS_COMMON::Options::environment()
|
|
#endif
|
|
#if defined(US_SDK_TEST_CHINA)
|
|
, OnlineAccessContext::China
|
|
#else
|
|
, OnlineAccessContext::Standard
|
|
#endif
|
|
#if !defined(US_SDK_S2S)
|
|
, GameConfigEvent(US_SDK_VERSION_CONST_CHAR
|
|
, US_TEST_NS::US_SDK_DUMMY_GAME_SKU
|
|
, LeakChecker_BF::getDefaultEventTypesForSaveGame()
|
|
, StringJson("{}")
|
|
, NS_COMMON::Options::getApplicationSecretKey().c_str())
|
|
#endif //!defined(US_SDK_S2S)
|
|
|
|
#if defined(US_TARGET_PS4) || defined(US_TARGET_SWITCH) || defined(US_TARGET_XONE) || defined(US_TARGET_GGP) || defined(US_TARGET_KILI)
|
|
, GameConfigConsole(NS_COMMON::FIRSTPARTY_APP_ID)
|
|
#endif
|
|
);
|
|
|
|
const SystemConfig systemConfig(US_NS::ThreadingConfig(), httpConfig);
|
|
|
|
const US_NS::ConfigureResult result = configureSdk(gameConfig, systemConfig);
|
|
if (result != ConfigureResult::Success)
|
|
{
|
|
PRINT_DEBUG("configureSdk FAILED with error : %d", result);
|
|
}
|
|
EXPECT_EQ(result, ConfigureResult::Success);
|
|
|
|
#if !defined(US_SDK_S2S)
|
|
EXPECT_TRUE(InstancesHelper::SetBackdoorEnvironment(NS_COMMON::Options::environment()));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void LeakChecker::uninitDefaultSDK()
|
|
{
|
|
US_TEST_NS::Helper::uninitializeSdk();
|
|
}
|
|
|
|
#if defined(US_USE_LIBCURL) && !defined(US_DLL) && !defined(US_TARGET_SWITCH)
|
|
void LeakCheckerNoLibcurlEalMem::SetUp()
|
|
{
|
|
g_skipEalMemForLibcurl = true;
|
|
LeakChecker::SetUp();
|
|
}
|
|
#endif
|
|
|
|
LeakCheckerScopedInit::LeakCheckerScopedInit(LeakChecker& testInstance)
|
|
: m_testInstance(testInstance)
|
|
{
|
|
m_testInstance.LeakChecker::initDefaultSDK();
|
|
}
|
|
|
|
LeakCheckerScopedInit::~LeakCheckerScopedInit()
|
|
{
|
|
m_testInstance.LeakChecker::uninitDefaultSDK();
|
|
}
|
|
|
|
};
|