| /*========================================================================= |
| * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * one or more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| #include "fw_dunit.hpp" |
| #include "ThinClientHelper.hpp" |
| #include <gfcpp/statistics/StatisticsFactory.hpp> |
| |
| #include <ace/ACE.h> |
| #include <ace/Guard_T.h> |
| #include <ace/Thread_Mutex.h> |
| #include <ace/OS.h> |
| #include <ace/OS_NS_time.h> |
| #include <ace/OS_NS_sys_time.h> |
| #include <ace/OS_NS_unistd.h> |
| #include <ace/OS_NS_Thread.h> |
| #include <ace/Dirent.h> |
| #include <ace/Dirent_Selector.h> |
| #include <ace/OS_NS_sys_stat.h> |
| |
| /* This is to test Statistics Functionality, Following Parameters are considered |
| 1- Creation of Stats Type / Statistics / Statistics Descriptors ( int_t/ Long / Double , Counter / Gauge ) . |
| 2- Use Functions Get/ Set / Inc in normal / abnormal way. and check consistency in single / multithreaded env. |
| */ |
| |
| #define CLIENT1 s1p1 |
| #define CLIENT2 s1p2 |
| #define SERVER1 s2p1 |
| #define CLIENT3 s2p2 |
| const char* g_ClientName; |
| const char* MyClients[] = { "MyClientA", "MyClientB", "MyClientC" }; |
| int LogFileSettings[] = { 1, 2, 100 }; |
| int MyResults[] = { 1*1024*1024, 2*1024*1024, 5*1024*1024 }; |
| int NumberOfFiles[] = { 10, 2, 1 }; |
| int DiskFileSettings[] = { 10, 3, 5 }; |
| |
| #define EPSILON 0.0000001 |
| |
| bool isLocalServer = false; |
| const char * endPoint = CacheHelper::getTcrEndpoints( isLocalServer, 1 ); |
| |
| bool IsDoubleEqual ( double d1 , double d2 ) { |
| double diff = d1 > d2 ? (d1-d2) : (d2-d1); |
| return ( diff < EPSILON ) ? true: false; |
| } |
| |
| struct TestStatisticsType { |
| StatisticsType* testStatsType; |
| int statIdIntCounter; |
| int statIdIntGauge; |
| int statIdLongCounter; |
| int statIdLongGauge; |
| int statIdDoubleCounter; |
| int statIdDoubleGauge; |
| }; |
| |
| class IncThread : public ACE_Task_Base |
| { |
| private: |
| Statistics* m_stat; |
| TestStatisticsType* m_type; |
| |
| public: |
| IncThread(Statistics* stat,TestStatisticsType* type ): |
| m_stat(stat), m_type(type) { } |
| |
| int svc(void) |
| { |
| /* Just 1000 Inc, Stop after that */ |
| for ( int incIdx = 0 ; incIdx < 1000 ; incIdx++ ) { |
| m_stat->incInt(m_type->statIdIntCounter, 1 ); |
| m_stat->incInt(m_type->statIdIntGauge, 1 ); |
| m_stat->incLong(m_type->statIdLongCounter, 1 ); |
| m_stat->incLong(m_type->statIdLongGauge, 1 ); |
| m_stat->incDouble(m_type->statIdDoubleCounter, 1.0 ); |
| m_stat->incDouble(m_type->statIdDoubleGauge, 1.0 ); |
| } |
| //LOG(" Incremented 1000 times by thread."); |
| return 0; |
| } |
| void start() |
| { |
| activate(); |
| } |
| void stop() |
| { |
| wait(); |
| } |
| }; |
| |
| static int comparator (const dirent **d1, const dirent **d2) |
| { |
| if (strlen((*d1)->d_name) < strlen((*d2)->d_name) ) |
| return -1; |
| else if(strlen((*d1)->d_name) > strlen((*d2)->d_name) ) |
| return 1; |
| |
| int diff = ACE_OS::strcmp ((*d1)->d_name, (*d2)->d_name); |
| if ( diff < 0 ) |
| return -1; |
| else if (diff > 0 ) |
| return 1; |
| else |
| return 0; |
| } |
| |
| static int selector (const dirent *d) |
| { |
| std::string inputname(d->d_name); |
| LOGINFO("selector %s\t g_ClientName = %s", inputname.c_str(), g_ClientName); |
| return ACE_OS::strstr (d->d_name, g_ClientName) != 0; |
| } |
| |
| /* Common Functions */ |
| void initClientWithStats( ) |
| { |
| PropertiesPtr pp = Properties::create(); |
| pp->insert("statistic-sampling-enabled", "true"); |
| pp->insert("statistic-sample-rate", 1); |
| pp->insert("statistic-archive-file", "./statArchive.gfs"); |
| pp->insert( "notify-ack-interval", 1 ); |
| |
| initClient( true,pp ); |
| createRegion( regionNames[0], USE_ACK, endPoint, true); |
| } |
| |
| void initClientWithStatsDisabled( ) |
| { |
| PropertiesPtr pp = Properties::create(); |
| pp->insert("statistic-sampling-enabled", "false"); |
| //pp->insert("statistic-sample-rate", 1); |
| //pp->insert("statistic-archive-file", "./statArchive.gfs"); |
| |
| initClient( true,pp ); |
| createRegion( regionNames[0], USE_ACK, endPoint, true); |
| } |
| |
| void DoRegionOpsAndVerify(){ |
| RegionPtr regPtr0 = getHelper()->getRegion(regionNames[0]); |
| |
| for (int index=0; index < 5; index++){ |
| char key[100] = {0}; |
| char value[100] = {0}; |
| ACE_OS::sprintf(key, "Key-%d", index); |
| ACE_OS::sprintf(value, "Value-%d", index); |
| CacheableKeyPtr keyptr = CacheableKey::create(key); |
| CacheablePtr valuePtr = CacheableString::create(value); |
| regPtr0->put(keyptr, valuePtr); |
| } |
| |
| CacheableKeyPtr keyptr = CacheableKey::create("Key-0"); |
| |
| RegionEntryPtr regEntry = regPtr0->getEntry(keyptr); |
| |
| LOGINFO("regEntry->isDestroyed() = %d ", regEntry->isDestroyed()); |
| ASSERT(regEntry->isDestroyed() == false, "regionEntry is not destroyed, regEntry->isDestroyed must return false"); |
| |
| bool flag = regPtr0->remove(keyptr); |
| |
| RegionEntryPtr remRegEntry = regPtr0->getEntry(keyptr); |
| ASSERT(remRegEntry == NULLPTR, "regionEntry pointer to removed entry must be NULLPTR"); |
| |
| if(remRegEntry != NULLPTR){ |
| LOGINFO("remRegEntry->isDestroyed() = %d ", remRegEntry->isDestroyed()); |
| ASSERT(remRegEntry->isDestroyed() == true, "regionEntry is not destroyed, remRegEntry->isDestroyed must return false"); |
| }else{ |
| LOGINFO("regionEntry pointer for removed key is NULL"); |
| } |
| |
| CacheStatisticsPtr cacheStatptr (new CacheStatistics()); |
| //CacheStatisticsPtr cacheStatptr; |
| try{ |
| bool flag = regPtr0->getCache()->getDistributedSystem()->getSystemProperties()->statisticsEnabled(); |
| LOGINFO("statisticsEnabled = %d ", flag); |
| regEntry->getStatistics(cacheStatptr); |
| }catch(StatisticsDisabledException& ex){ |
| LOGINFO("Exception Caught:: StatisticsDisabledException"); |
| }catch ( GemfireConfigException& e) { |
| LOGINFO("Exception Caught:: %s", e.getMessage()); |
| }catch (Exception& ex){ |
| LOGINFO("Exception Caught:: %s", ex.getMessage()); |
| } |
| if(cacheStatptr != NULLPTR){ |
| LOGINFO("LastAccessedTime = %d ", cacheStatptr->getLastAccessedTime()); |
| }else{ |
| LOGINFO("cacheStatptr is NULL"); |
| } |
| } |
| |
| void initClientWithStatsAndLog(const char* str, int fileLimit, int diskLimit ) |
| { |
| PropertiesPtr pp = Properties::create(); |
| pp->insert("log-file", str); |
| pp->insert("log-level", "fine"); |
| pp->insert("log-file-size-limit", fileLimit); |
| pp->insert("log-disk-space-limit", diskLimit); |
| initClient( true,pp ); |
| } |
| |
| void createType(StatisticsFactory* statFactory, TestStatisticsType& testType) |
| { |
| StatisticDescriptor** statDescriptorArr = new StatisticDescriptor*[6]; |
| statDescriptorArr[0] = statFactory->createIntCounter("IntCounter", |
| "Test Statistic Descriptor int_t Counter.","TestUnit"); |
| |
| statDescriptorArr[1] = statFactory->createIntGauge("IntGauge", |
| "Test Statistic Descriptor int_t Gauge.","TestUnit"); |
| |
| statDescriptorArr[2] = statFactory->createLongCounter("LongCounter", |
| "Test Statistic Descriptor Long Counter.","TestUnit"); |
| |
| statDescriptorArr[3] = statFactory->createLongGauge("LongGauge", |
| "Test Statistic Descriptor Long Gauge.","TestUnit"); |
| |
| statDescriptorArr[4] = statFactory->createDoubleCounter("DoubleCounter", |
| "Test Statistic Descriptor Double Counter.","TestUnit"); |
| |
| statDescriptorArr[5] = statFactory->createDoubleGauge("DoubleGauge", |
| "Test Statistic Descriptor Double Gauge.","TestUnit"); |
| |
| StatisticsType* statsType = statFactory->createType("TestStatsType", |
| "Statistics for Unit Test.",statDescriptorArr, 6); |
| |
| ASSERT(statsType != NULL , "Error in creating Stats Type" ); |
| |
| testType.testStatsType = statsType; |
| testType.statIdIntCounter = statsType->nameToId("IntCounter"); |
| testType.statIdIntGauge = statsType->nameToId("IntGauge"); |
| testType.statIdLongCounter = statsType->nameToId("LongCounter"); |
| testType.statIdLongGauge = statsType->nameToId("LongGauge"); |
| testType.statIdDoubleCounter = statsType->nameToId("DoubleCounter"); |
| testType.statIdDoubleGauge = statsType->nameToId("DoubleGauge"); |
| |
| /* Test Find */ |
| ASSERT(statsType == statFactory->findType("TestStatsType"), " Find Type Failed"); |
| } |
| |
| void testGetSetIncFunctions(Statistics* stat, TestStatisticsType& type ) |
| { |
| /* Set a initial value = 10 */ |
| stat->setInt(type.statIdIntCounter, 10 ); |
| stat->setInt(type.statIdIntGauge, 10 ); |
| stat->setLong(type.statIdLongCounter, 10 ); |
| stat->setLong(type.statIdLongGauge, 10 ); |
| stat->setDouble(type.statIdDoubleCounter, 10.0 ); |
| stat->setDouble(type.statIdDoubleGauge, 10.0 ); |
| LOG(" Setting Initial Value Complete"); |
| |
| /* Check Initial Value = 10*/ |
| ASSERT(10 == stat->getInt(type.statIdIntCounter) , " Check1 1 Failed "); |
| ASSERT(10 == stat->getInt(type.statIdIntGauge) , " Check1 2 Failed "); |
| ASSERT(10 == stat->getLong(type.statIdLongCounter) , " Check1 3 Failed "); |
| ASSERT(10 == stat->getLong(type.statIdLongGauge) , " Check1 4 Failed "); |
| ASSERT( IsDoubleEqual( 10.0 , stat->getDouble(type.statIdDoubleCounter) ) , " Check1 5 Failed "); |
| ASSERT( IsDoubleEqual( 10.0 , stat->getDouble(type.statIdDoubleGauge) ), " Check1 6 Failed "); |
| LOG(" All Set() were correct."); |
| |
| /* Increment single thread for 100 times */ |
| for ( int incIdx = 0 ; incIdx < 100 ; incIdx++ ) { |
| stat->incInt(type.statIdIntCounter, 1 ); |
| stat->incInt(type.statIdIntGauge, 1 ); |
| stat->incLong(type.statIdLongCounter, 1 ); |
| stat->incLong(type.statIdLongGauge, 1 ); |
| stat->incDouble(type.statIdDoubleCounter, 1.0 ); |
| stat->incDouble(type.statIdDoubleGauge, 1.0 ); |
| SLEEP(10); |
| } |
| LOG(" Incremented 100 times by 1."); |
| |
| /* Check Incremented Value = 110 */ |
| ASSERT(110 == stat->getInt(type.statIdIntCounter) , " Check2 1 Failed "); |
| ASSERT(110 == stat->getInt(type.statIdIntGauge) , " Check2 2 Failed "); |
| ASSERT(110 == stat->getLong(type.statIdLongCounter) , " Check2 3 Failed "); |
| ASSERT(110 == stat->getLong(type.statIdLongGauge) , " Check2 4 Failed "); |
| ASSERT( IsDoubleEqual( 110.0 , stat->getDouble(type.statIdDoubleCounter) ) , " Check2 5 Failed "); |
| ASSERT( IsDoubleEqual( 110.0 , stat->getDouble(type.statIdDoubleGauge) ), " Check2 6 Failed "); |
| LOG(" Single thread Inc() Passed."); |
| |
| /* Increment parallelly = 10,000 times */ |
| IncThread* threads[10]; |
| for(int thdIdx = 0; thdIdx < 10; thdIdx++) { |
| threads[thdIdx] = new IncThread(stat, &type); |
| threads[thdIdx]->start(); |
| } |
| SLEEP(1000); |
| for(int thdIdx = 0; thdIdx < 10; thdIdx++) { |
| threads[thdIdx]->stop(); |
| } |
| |
| /* Check Final Value = 10,110 */ |
| ASSERT(10110 == stat->getInt(type.statIdIntCounter) , " Check2 1 Failed "); |
| ASSERT(10110 == stat->getInt(type.statIdIntGauge) , " Check2 2 Failed "); |
| ASSERT(10110 == stat->getLong(type.statIdLongCounter) , " Check2 3 Failed "); |
| ASSERT(10110 == stat->getLong(type.statIdLongGauge) , " Check2 4 Failed "); |
| ASSERT( IsDoubleEqual( 10110.0 , stat->getDouble(type.statIdDoubleCounter) ) , " Check2 5 Failed "); |
| ASSERT( IsDoubleEqual( 10110.0 , stat->getDouble(type.statIdDoubleGauge) ), " Check2 6 Failed "); |
| LOG(" Parallel Inc() Passed."); |
| } |
| |
| void statisticsTest( ) |
| { |
| /* Create Statistics in right and wrong manner */ |
| StatisticsFactory* factory = StatisticsFactory::getExistingInstance(); |
| |
| /* Register a type */ |
| TestStatisticsType testType; |
| createType(factory, testType); |
| LOG("Statistics Type TestStats Registered"); |
| |
| /* Create a statistics */ |
| Statistics* testStat1 = factory->createStatistics(testType.testStatsType,"TestStatistics"); |
| ASSERT(testStat1 != NULL, "Test Statistics Creation Failed"); |
| |
| /* Tests Find Type , Find Statistics */ |
| Statistics* temp = factory->findFirstStatisticsByType(testType.testStatsType); |
| ASSERT(temp == testStat1, "findFirstStatisticsByType Failed"); |
| LOG("Statistics testStat1 Created Successfully."); |
| |
| /* Test Set Functions */ |
| testGetSetIncFunctions( testStat1, testType ); |
| LOG("Get / Set / Inc Functions Tested "); |
| |
| /* Close Statistics */ |
| testStat1->close(); |
| Statistics* temp2 = factory->findFirstStatisticsByType(testType.testStatsType); |
| ASSERT(temp2 == NULL, "Statistics close() Failed"); |
| |
| LOG("StatisticsTest Completed"); |
| } |
| |
| void LogTest(int expectedResult, int noofFiles, int diskLimit ) |
| { |
| unsigned int seed = 2; |
| int rand1 = (int) ACE_OS::rand_r(&seed)%2; |
| unsigned int seed2 = 700; |
| int rand2 = (int) ACE_OS::rand_r(&seed2)%700; |
| |
| int rand = (rand1 + 8) * 1024 + rand2; |
| LOGFINE(" random is %d",rand); |
| char buf [ 10*1024 ]; |
| for (int i=0;i< rand - 1;i++) |
| buf[i] = 'A'; |
| buf[10*1024-1] = '\0'; |
| for (int j=0;j<2*1024;j++) |
| { |
| LOGFINE("%s",buf); |
| } |
| std::string dirname = ACE::dirname("."); |
| struct dirent **resultArray; |
| LOGFINE("dirname is %s ", dirname.c_str()); |
| int entries_count = ACE_OS::scandir(dirname.c_str(), &resultArray, selector, comparator); |
| LOGFINE("entries_count is %d ", entries_count); |
| ASSERT(entries_count == noofFiles, "files count should be equal to noofFiles"); |
| ACE_stat statBuf; |
| int spaceUsed = 0; |
| char fullpath[512] = {0}; |
| for(int i = 0; i < entries_count; i++) { |
| sprintf(fullpath,"%s%c%s",dirname.c_str(),ACE_DIRECTORY_SEPARATOR_CHAR,resultArray[i]->d_name); |
| LOGFINE("fullpath is %s ", fullpath); |
| ACE_OS::stat(fullpath,&statBuf); |
| int size = statBuf.st_size; |
| ASSERT(size <= expectedResult, "individual file size should be less than equal to expectedResult"); |
| spaceUsed += size; |
| } |
| LOGFINE("spaceUsed is %d ", spaceUsed); |
| ASSERT(spaceUsed <= 1024*1024*diskLimit, "collective file size should be less than equal to diskLimit"); |
| LOG("LogTest Completed"); |
| } |
| |
| void StatFileTest() |
| { |
| LOG(" Starting Stat.gfs file test"); |
| /* Get Pid , Get File name : HARD Coding for File name pattern */ |
| char buff[1024]; |
| int32 pid = ACE_OS::getpid(); |
| ACE_OS::sprintf(buff,"./statArchive-%d.gfs", pid); |
| std::string statFilename(buff); |
| |
| /* Test if this file Stat-pid.gfs is there */ |
| FILE * fp = fopen(statFilename.c_str(), "r"); |
| ASSERT(fp != NULL , "Statistics GFS file does not exist"); |
| if ( fp != NULL ) { |
| LOG("SUCCESS: .gfs file exist."); |
| fclose(fp); |
| } |
| |
| /* Load File in Stat Reader and check If it returns true */ |
| char cmd[1024]; |
| char * gfjavaenv = ACE_OS::getenv( "GFJAVA" ); |
| ASSERT( gfjavaenv != NULL, "Environment variable GFJAVA for java build directory is not set." ); |
| ACE_OS::sprintf( cmd, "%s/bin/gemfire stats -archive=%s", gfjavaenv, statFilename.c_str() ); |
| |
| LOG( cmd ); |
| if( ACE_OS::system( cmd ) != 0 ) { |
| FAIL(" Statistics File Read failed"); |
| }else { |
| LOG("SUCCESS: .gfs file is consistent."); |
| } |
| |
| LOG(" StatFileTest complete."); |
| } |
| |
| /* Test Tasks */ |
| DUNIT_TASK(SERVER1, StartServer) |
| { |
| if ( isLocalServer ) |
| CacheHelper::initServer( 1 , "cacheserver_notify_subscription.xml"); |
| LOG("SERVER started"); |
| } |
| END_TASK(StartServer) |
| |
| DUNIT_TASK(CLIENT1, ClientInit) |
| { |
| initClientWithStats(); |
| LOG( "Client Init complete." ); |
| } |
| END_TASK(ClientInit) |
| |
| DUNIT_TASK(CLIENT1, StatTest) |
| { |
| statisticsTest(); |
| } |
| END_TASK(StatTest) |
| |
| DUNIT_TASK(CLIENT1,CloseClient) |
| { |
| cleanProc(); |
| LOG("CLIENT closed"); |
| } |
| END_TASK(CloseClient) |
| |
| DUNIT_TASK(CLIENT1,GFSFileTest) |
| { |
| StatFileTest(); |
| } |
| END_TASK(GFSFileTest) |
| |
| DUNIT_TASK(SERVER1 , CloseServer) |
| { |
| CacheHelper::closeServer( 1 ); |
| LOG("SERVER closed"); |
| } |
| END_TASK(CloseServer) |
| |
| DUNIT_TASK(SERVER1, StartServer) |
| { |
| if ( isLocalServer ) |
| CacheHelper::initServer( 1 , "cacheserver_notify_subscription.xml"); |
| LOG("SERVER started"); |
| } |
| END_TASK(StartServer) |
| |
| DUNIT_TASK(CLIENT1, ClientInit) |
| { |
| g_ClientName = MyClients[0]; |
| initClientWithStatsAndLog(MyClients[0], LogFileSettings[0], DiskFileSettings[0]); |
| LogTest(MyResults[0], NumberOfFiles[0], DiskFileSettings[0]); |
| cleanProc(); |
| g_ClientName = MyClients[1]; |
| initClientWithStatsAndLog(MyClients[1], LogFileSettings[1], DiskFileSettings[1]); |
| LogTest(MyResults[1], NumberOfFiles[1], DiskFileSettings[1]); |
| cleanProc(); |
| g_ClientName = MyClients[2]; |
| initClientWithStatsAndLog(MyClients[2], LogFileSettings[2], DiskFileSettings[2]); |
| LogTest(MyResults[2], NumberOfFiles[2], DiskFileSettings[2]); |
| cleanProc(); |
| } |
| END_TASK(ClientInit) |
| |
| DUNIT_TASK(SERVER1 , CloseServer) |
| { |
| CacheHelper::closeServer( 1 ); |
| LOG("SERVER closed"); |
| } |
| END_TASK(CloseServer) |
| |
| //ADDED FOR TEST-COVERAGE |
| DUNIT_TASK(SERVER1, StartServer) |
| { |
| if ( isLocalServer ) |
| CacheHelper::initServer( 1 , "cacheserver_notify_subscription.xml"); |
| LOG("SERVER started"); |
| } |
| END_TASK(StartServer) |
| |
| DUNIT_TASK(CLIENT1, ClientInit) |
| { |
| initClientWithStatsDisabled(); |
| LOG( "Client Init complete." ); |
| } |
| END_TASK(ClientInit) |
| |
| DUNIT_TASK(CLIENT1, RegionOps) |
| { |
| DoRegionOpsAndVerify(); |
| } |
| END_TASK(StatTest) |
| |
| DUNIT_TASK(CLIENT1,CloseClient) |
| { |
| cleanProc(); |
| LOG("CLIENT closed"); |
| } |
| END_TASK(CloseClient) |
| |
| |
| DUNIT_TASK(SERVER1 , CloseServer) |
| { |
| CacheHelper::closeServer( 1 ); |
| LOG("SERVER closed"); |
| } |
| END_TASK(CloseServer) |