[mapguide-commits] r9599 - trunk/MgDev/Server/src/UnitTesting
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Sep 11 00:21:40 PDT 2019
Author: jng
Date: 2019-09-11 00:21:40 -0700 (Wed, 11 Sep 2019)
New Revision: 9599
Modified:
trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp
trunk/MgDev/Server/src/UnitTesting/TestMisc.h
Log:
#2401: Add multi-threaded MgConfiguration access test to verify that GetBoolValue is indeed thread-safe
Modified: trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp 2019-09-02 11:51:01 UTC (rev 9598)
+++ trunk/MgDev/Server/src/UnitTesting/TestMisc.cpp 2019-09-11 07:21:40 UTC (rev 9599)
@@ -25,7 +25,12 @@
#include "FdoConnectionManager.h"
const STRING TEST_LOCALE = L"en";
+static const INT32 MG_TEST_THREADS = 16;
+// define thread group for config tests
+#define THREAD_GROUP 65520
+#define TESTREQUESTS 5000
+
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(TestMisc, "TestMisc");
TestMisc::TestMisc()
@@ -771,4 +776,140 @@
{
throw;
}
+}
+
+// data structure which is passed to each thread
+struct GetConfigValueThreadData
+{
+ INT32 threadId;
+ bool success;
+ bool done;
+ STRING section;
+ STRING key;
+};
+
+ACE_THR_FUNC_RETURN GetConfigValueWorker(void* param)
+{
+ // get the data for this thread
+ GetConfigValueThreadData* threadData = (GetConfigValueThreadData*)param;
+ INT32 threadId = threadData->threadId;
+#ifdef _DEBUG
+ printf("> thread %d started, tile %d,%d\n", threadId, tileRow, tileCol);
+#endif
+
+ try
+ {
+ MgConfiguration* conf = MgConfiguration::GetInstance();
+ bool b = false;
+ conf->GetBoolValue(threadData->section, threadData->key, b, false);
+
+ threadData->success = true;
+ }
+ catch (MgException* e)
+ {
+ threadData->success = false;
+ STRING message = e->GetDetails(TEST_LOCALE);
+ SAFE_RELEASE(e);
+ CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+ }
+ catch (...)
+ {
+ threadData->success = false;
+ throw;
+ }
+
+#ifdef _DEBUG
+ // printf("> thread %d done\n", threadId);
+#endif
+
+ threadData->done = true;
+ return 0;
+}
+
+void TestMisc::TestCase_ThreadSafeConfiguration()
+{
+ try
+ {
+ // specify the number of threads to use
+ const INT32 numThreads = MG_TEST_THREADS;
+ GetConfigValueThreadData threadData[numThreads];
+
+ // need a thread manager
+ ACE_Thread_Manager* manager = ACE_Thread_Manager::instance();
+
+ // initialize the thread data
+ for (INT32 i = 0; i < numThreads; i++)
+ {
+ threadData[i].threadId = i;
+ threadData[i].done = true;
+ threadData[i].success = true;
+ threadData[i].section = MgConfigProperties::GeneralPropertiesSection;
+ threadData[i].key = MgConfigProperties::GeneralPropertyMaxLogFileSizeEnabled;
+ }
+
+ INT32 nRequest = 0;
+ INT32 nSuccessful = 0;
+ INT32 nFailed = 0;
+ bool bExceptionOcurred = false;
+ for (;;)
+ {
+ INT32 dc = 0;
+ for (INT32 i = 0; i < numThreads; i++)
+ {
+ // check if the thread is available
+ if (threadData[i].done)
+ {
+ if (threadData[i].success)
+ nSuccessful++;
+ else
+ nFailed++;
+
+ // Reset for next run
+ threadData[i].success = true;
+ threadData[i].done = false;
+
+ // spawn a new thread using a specific group id
+ int thid = manager->spawn(ACE_THR_FUNC(GetConfigValueWorker), &threadData[i], 0, NULL, NULL, 0, THREAD_GROUP);
+ nRequest++;
+ }
+ }
+
+ // move on if all threads are done
+ if ((nRequest > TESTREQUESTS) || (bExceptionOcurred))
+ break;
+
+ // under Linux we get a deadlock if we don't call this every once in a while
+ if (nRequest % 25 == 0)
+ manager->wait_grp(THREAD_GROUP);
+ else
+ {
+ // pause briefly (10ms) before checking again
+ ACE_Time_Value t(0, 10000);
+ ACE_OS::sleep(t);
+ }
+ }
+
+ // make sure all threads in the group have completed
+ manager->wait_grp(THREAD_GROUP);
+
+ for (INT32 i = 0; i < numThreads; i++)
+ {
+ if (threadData[i].success)
+ nSuccessful++;
+ else
+ nFailed++;
+ }
+
+ CPPUNIT_ASSERT(nFailed == 0);
+ }
+ catch (MgException* e)
+ {
+ STRING message = e->GetDetails(TEST_LOCALE);
+ SAFE_RELEASE(e);
+ CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+ }
+ catch (...)
+ {
+ throw;
+ }
}
\ No newline at end of file
Modified: trunk/MgDev/Server/src/UnitTesting/TestMisc.h
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestMisc.h 2019-09-02 11:51:01 UTC (rev 9598)
+++ trunk/MgDev/Server/src/UnitTesting/TestMisc.h 2019-09-11 07:21:40 UTC (rev 9599)
@@ -34,6 +34,7 @@
CPPUNIT_TEST(TestCase_DoubleToStringWithDecimals);
CPPUNIT_TEST(TestCase_TryParseDouble);
CPPUNIT_TEST(TestCase_BadResourceIdentifier);
+ CPPUNIT_TEST(TestCase_ThreadSafeConfiguration);
CPPUNIT_TEST(TestEnd); // This must be the very last unit test
CPPUNIT_TEST_SUITE_END();
@@ -57,6 +58,7 @@
void TestCase_DoubleToStringWithDecimals();
void TestCase_TryParseDouble();
void TestCase_BadResourceIdentifier();
+ void TestCase_ThreadSafeConfiguration();
private:
Ptr<MgSiteConnection> m_siteConnection;
More information about the mapguide-commits
mailing list