summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorj.alex <j.alex>2006-04-27 18:47:12 +0000
committerj.alex <j.alex>2006-04-27 18:47:12 +0000
commit14c3278abd63a4b545ba6f068030064095ccb7e4 (patch)
treeb5bfff7f7643a9e599435cb45abe537495b1fd11 /test
parent6f43ce52942d82dd4297544622e3586328beefdf (diff)
downloadtog-pegasus-14c3278abd63a4b545ba6f068030064095ccb7e4.zip
tog-pegasus-14c3278abd63a4b545ba6f068030064095ccb7e4.tar.gz
tog-pegasus-14c3278abd63a4b545ba6f068030064095ccb7e4.tar.xz
PEP#: 241
TITLE: OpenPegasus Stress Tests DESCRIPTION: OpenPegasus Stress Testing Code Modified Files: pegasus/Makefile pegasus/TestMakefile pegasus/test/Makefile Added Files: pegasus/test/StressTestClients/Linkage.h pegasus/test/StressTestClients/Makefile pegasus/test/StressTestClients/TestStressTestClient.cpp pegasus/test/StressTestClients/TestStressTestClient.h pegasus/test/StressTestClients/ModelWalkStressClient/Makefile pegasus/test/StressTestClients/ModelWalkStressClient/TestModelWalkStressClient.cpp pegasus/test/StressTestClients/WrapperStressClient/Makefile pegasus/test/StressTestClients/WrapperStressClient/TestWrapperStressClient.cpp pegasus/test/StressTestController/Makefile pegasus/test/StressTestController/README pegasus/test/StressTestController/StressTestController.cpp pegasus/test/StressTestController/StressTestController.h pegasus/test/StressTestController/StressTestControllerException.cpp pegasus/test/StressTestController/StressTestControllerException.h pegasus/test/StressTestController/StressTestControllerMain.cpp pegasus/test/StressTestController/default_stresstest.conf pegasus/test/StressTestController/tests/Makefile pegasus/test/StressTestController/tests/invalid_configuration.conf pegasus/test/StressTestController/tests/invalid_noclients.conf pegasus/test/StressTestController/tests/result.master
Diffstat (limited to 'test')
-rw-r--r--test/Makefile7
-rw-r--r--test/StressTestClients/Linkage.h46
-rw-r--r--test/StressTestClients/Makefile52
-rw-r--r--test/StressTestClients/ModelWalkStressClient/Makefile65
-rw-r--r--test/StressTestClients/ModelWalkStressClient/TestModelWalkStressClient.cpp930
-rw-r--r--test/StressTestClients/TestStressTestClient.cpp417
-rw-r--r--test/StressTestClients/TestStressTestClient.h184
-rw-r--r--test/StressTestClients/WrapperStressClient/Makefile59
-rw-r--r--test/StressTestClients/WrapperStressClient/TestWrapperStressClient.cpp360
-rw-r--r--test/StressTestController/Makefile52
-rw-r--r--test/StressTestController/README539
-rw-r--r--test/StressTestController/StressTestController.cpp3479
-rw-r--r--test/StressTestController/StressTestController.h551
-rw-r--r--test/StressTestController/StressTestControllerException.cpp141
-rw-r--r--test/StressTestController/StressTestControllerException.h145
-rw-r--r--test/StressTestController/StressTestControllerMain.cpp429
-rw-r--r--test/StressTestController/default_stresstest.conf12
-rw-r--r--test/StressTestController/tests/Makefile117
-rw-r--r--test/StressTestController/tests/invalid_configuration.conf6
-rw-r--r--test/StressTestController/tests/invalid_noclients.conf1
-rw-r--r--test/StressTestController/tests/result.master109
21 files changed, 7700 insertions, 1 deletions
diff --git a/test/Makefile b/test/Makefile
index 5f85822..ce9118d 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -33,7 +33,12 @@ ROOT = ..
include $(ROOT)/mak/config.mak
DIRS = \
- wetest
+ wetest \
+ StressTestController\
+ StressTestController/tests\
+ StressTestClients\
+ StressTestClients/ModelWalkStressClient \
+ StressTestClients/WrapperStressClient
include $(ROOT)/mak/recurse.mak
diff --git a/test/StressTestClients/Linkage.h b/test/StressTestClients/Linkage.h
new file mode 100644
index 0000000..6aa4bd5
--- /dev/null
+++ b/test/StressTestClients/Linkage.h
@@ -0,0 +1,46 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include <Pegasus/Common/Config.h>
+
+#ifndef PEGASUS_STRESSTESTCLIENT_LINKAGE
+# ifdef PEGASUS_OS_TYPE_WINDOWS
+# ifdef PEGASUS_STRESSTESTCLIENT_INTERNAL
+# define PEGASUS_STRESSTESTCLIENT_LINKAGE PEGASUS_EXPORT
+# else
+# define PEGASUS_STRESSTESTCLIENT_LINKAGE PEGASUS_IMPORT
+# endif
+# else
+# define PEGASUS_STRESSTESTCLIENT_LINKAGE
+# endif
+#endif
diff --git a/test/StressTestClients/Makefile b/test/StressTestClients/Makefile
new file mode 100644
index 0000000..e37697f
--- /dev/null
+++ b/test/StressTestClients/Makefile
@@ -0,0 +1,52 @@
+#//%2006////////////////////////////////////////////////////////////////////////
+#//
+#// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+#// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+#// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation, The Open Group.
+#// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; Symantec Corporation; The Open Group.
+#//
+#// Permission is hereby granted, free of charge, to any person obtaining a copy
+#// of this software and associated documentation files (the "Software"), to
+#// deal in the Software without restriction, including without limitation the
+#// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+#// sell copies of the Software, and to permit persons to whom the Software is
+#// furnished to do so, subject to the following conditions:
+#//
+#// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+#// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+#// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+#// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+#// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+#// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#//
+#//==============================================================================
+ROOT = $(PEGASUS_ROOT)
+
+DIR = test/StressTestClients
+include $(ROOT)/mak/config.mak
+
+ifdef PEGASUS_HAS_SSL
+ FLAGS += -DPEGASUS_HAS_SSL -DPEGASUS_SSL_RANDOMFILE
+ SYS_INCLUDES += -I$(OPENSSL_HOME)/include
+endif
+
+LOCAL_DEFINES = -DPEGASUS_STRESSTESTCLIENT_INTERNAL -DPEGASUS_INTERNALONLY
+
+LIBRARY = TestStressTestClient
+
+LIBRARIES = \
+ pegclient \
+ pegcommon
+
+SOURCES = \
+ TestStressTestClient.cpp
+
+include $(ROOT)/mak/library.mak
diff --git a/test/StressTestClients/ModelWalkStressClient/Makefile b/test/StressTestClients/ModelWalkStressClient/Makefile
new file mode 100644
index 0000000..72caf30
--- /dev/null
+++ b/test/StressTestClients/ModelWalkStressClient/Makefile
@@ -0,0 +1,65 @@
+#//%2006////////////////////////////////////////////////////////////////////////
+#//
+#// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+#// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+#// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation, The Open Group.
+#// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; Symantec Corporation; The Open Group.
+#//
+#// Permission is hereby granted, free of charge, to any person obtaining a copy
+#// of this software and associated documentation files (the "Software"), to
+#// deal in the Software without restriction, including without limitation the
+#// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+#// sell copies of the Software, and to permit persons to whom the Software is
+#// furnished to do so, subject to the following conditions:
+#//
+#// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+#// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+#// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+#// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+#// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+#// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#//
+#//==============================================================================
+ROOT = $(PEGASUS_ROOT)
+
+DIR = test/StressTestClients/ModelWalkStressClient
+
+include $(ROOT)/mak/config.mak
+
+ifdef PEGASUS_HAS_SSL
+ FLAGS += -DPEGASUS_HAS_SSL -DPEGASUS_SSL_RANDOMFILE
+ SYS_INCLUDES += -I$(OPENSSL_HOME)/include
+endif
+
+LIBRARIES = \
+ TestStressTestClient \
+ pegclient \
+ pegcommon \
+
+PROGRAM = TestModelWalkStressClient
+
+SOURCES = \
+ TestModelWalkStressClient.cpp
+
+ifneq ($(PEGASUS_PLATFORM),ZOS_ZSERIES_IBM)
+ ifneq ($(OS),HPUX)
+ ifdef PEGASUS_ENABLE_SLP
+ LIBRARIES += pegslp
+ endif
+ endif
+endif
+
+include $(ROOT)/mak/program.mak
+
+tests:
+
+poststarttests:
+
diff --git a/test/StressTestClients/ModelWalkStressClient/TestModelWalkStressClient.cpp b/test/StressTestClients/ModelWalkStressClient/TestModelWalkStressClient.cpp
new file mode 100644
index 0000000..ed44656
--- /dev/null
+++ b/test/StressTestClients/ModelWalkStressClient/TestModelWalkStressClient.cpp
@@ -0,0 +1,930 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: Aruran, IBM (aruran.shanmug@in.ibm.com)
+//
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include "../TestStressTestClient.h"
+
+PEGASUS_USING_PEGASUS;
+PEGASUS_USING_STD;
+
+Boolean verboseTest = false;
+
+Boolean quit = false;
+Boolean nextCheck = false;
+int status = CLIENT_UNKNOWN;
+char clientName[] = "ModelWalkStressClient";
+
+String errorInfo;
+
+/**
+ Signal handler for SIGALARM.
+ @param signum - the alarm identifier.
+*/
+void endTest(int signum)
+{
+ PEGASUS_STD(cout) << "\nRecieved interrupt signal SIGINT!\n"
+ << PEGASUS_STD(endl);
+ quit = true;
+}
+
+class TestModelWalkStressClient:public TestStressTestClient
+{
+};
+
+/**
+ GetNameSpaces
+ If no nameSpace is supplied on the command line, this method looks into
+ the root and test nameSpaces for the _Namespace class. The names of the
+ instances of that class are retrued by this method.
+*/
+Array<CIMNamespaceName> getNameSpaces(
+ TestModelWalkStressClient &tmsc,
+ CIMClient* client,
+ OptionManager &om,
+ pid_t clientPid,
+ String& clientLog,
+ String &clientId,
+ int status,
+ String &pidFile)
+{
+ Array<CIMNamespaceName> topNamespaceNames;
+ Array<CIMNamespaceName> returnNamespaces;
+ String tmpNamespace;
+
+ om.lookupValue("namespace",tmpNamespace);
+ if (tmpNamespace != String::EMPTY)
+ {
+ returnNamespaces.append(CIMNamespaceName (tmpNamespace));
+ }
+ else
+ {
+ //
+ // Get all namespaces for display using the __Namespaces function.
+ //
+ CIMName className = "__NameSpace";
+
+ //
+ // We have to append any new top level root namespace if created in
+ // repository.
+ //
+ topNamespaceNames.append("root");
+ topNamespaceNames.append("test");
+
+ Uint32 start = 0;
+ Uint32 end = topNamespaceNames.size();
+
+ //
+ // for all new elements in the output array.
+ //
+ for (Uint32 range = start; range < end; range ++)
+ {
+ //
+ // Get the next increment in naming for all name element in
+ // the array.
+ //
+ Array<CIMInstance> instances = client->enumerateInstances(
+ topNamespaceNames[range], className);
+
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ for (Uint32 i = 0 ; i < instances.size(); i++)
+ {
+ Uint32 pos;
+ //
+ // if we find the property and it is a string, use it.
+ //
+ if ((pos = instances[i].findProperty("name")) != PEG_NOT_FOUND)
+ {
+ CIMValue value;
+ String namespaceComponent;
+ value = instances[i].getProperty(pos).getValue();
+ if (value.getType() == CIMTYPE_STRING)
+ {
+ value.get(namespaceComponent);
+ String ns = topNamespaceNames[range].getString();
+ ns.append("/");
+ ns.append(namespaceComponent);
+ returnNamespaces.append(ns);
+ }
+ }
+ }
+ }
+ }//else block ends here...
+
+ if (verboseTest)
+ {
+ errorInfo.clear();
+ errorInfo.append("+++++ Successfully Enumerated all Namespaces that ");
+ errorInfo.append("have a _NameSpace instance defined for them in the");
+ errorInfo.append(" root of test namespaces +++++");
+ tmsc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+ return returnNamespaces;
+}
+/**
+ EnumerateAllQualifiers
+ This method enumerates all the qualifiers in each of the nameSpaces
+ of the "nameSpacesArray"
+*/
+static void enumerateAllQualifiers(
+ TestModelWalkStressClient &tmsc,
+ CIMClient* client,
+ Array<CIMNamespaceName> nameSpacesArray,
+ pid_t clientPid,
+ String& clientLog,
+ String &clientId,
+ int status,
+ String &pidFile)
+{
+ Array<CIMQualifierDecl> qualifierDecls;
+ qualifierDecls.clear();
+
+ for (Uint32 i=0; i < nameSpacesArray.size();i++)
+ {
+ try
+ {
+ qualifierDecls = client->enumerateQualifiers(nameSpacesArray[i]);
+
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ }
+ //
+ // Following exceptions will be caught in the Main method.
+ //
+ catch (CIMException &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("CIMException in enumerateQualifiers : ");
+ errorInfo.append(e.getMessage());
+ CIMException cimExp(e.getCode(), errorInfo);
+ throw cimExp;
+ }
+ catch (Exception &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("Exception in enumerateQualifiers : ");
+ errorInfo.append(e.getMessage());
+ Exception exp(errorInfo);
+ throw exp;
+ }
+ catch (...)
+ {
+ Exception exp("General Exception in enumerateQualifiers ");
+ throw exp;
+ }
+ }
+
+ if (verboseTest)
+ {
+ errorInfo.clear();
+ errorInfo.append("+++++ Successfully Enumerated Qualifiers for ");
+ errorInfo.append("Namespaces +++++");
+ tmsc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+}
+/**
+ EnumerateReferenceNames
+ This method enumerates the references to each instance in the array
+ "cimInstances" for the "nameSpace"
+*/
+static void enumerateReferenceNames(
+ TestModelWalkStressClient &tmsc,
+ CIMClient* client,
+ Array<CIMInstance> cimNInstances,
+ CIMNamespaceName nameSpace,
+ CIMName referenceClass,
+ pid_t clientPid,
+ String& clientLog,
+ String &clientId,
+ int status,
+ String &pidFile)
+{
+ String role = String::EMPTY;
+ Array<CIMObjectPath> resultObjectPaths;
+
+ for (Uint32 i=0; i < cimNInstances.size(); i++)
+ {
+ try
+ {
+ resultObjectPaths = client->referenceNames(
+ nameSpace, cimNInstances[i].getPath(),
+ referenceClass, role);
+
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ }
+ //
+ // Following exceptions will be caught in the Main method.
+ //
+ catch (CIMException &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("CIMException in enumerateReferenceNames : ");
+ errorInfo.append(e.getMessage());
+ CIMException cimExp(e.getCode(), errorInfo);
+ throw cimExp;
+ }
+ catch (Exception &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("Exception in enumerateReferenceNames : ");
+ errorInfo.append(e.getMessage());
+ Exception exp(errorInfo);
+ throw exp;
+ }
+ catch (...)
+ {
+ Exception exp("General Exception in enumerateReferenceNames ");
+ throw exp;
+ }
+ }
+}
+/**
+ EnumerateAssociatorNames
+ This method enumerates the associators to each instance in the array
+ "cimInstances" for the "nameSpace"
+*/
+static void enumerateAssociatorNames(
+ TestModelWalkStressClient &tmsc,
+ CIMClient* client,
+ Array<CIMInstance> cimNInstances,
+ CIMNamespaceName nameSpace,
+ CIMName assocClass,
+ pid_t clientPid,
+ String& clientLog,
+ String &clientId,
+ int status,
+ String &pidFile)
+{
+ CIMName resultClass = CIMName();
+ String role = String::EMPTY;
+ String resultRole = String::EMPTY;
+ Array<CIMObjectPath> resultObjectPaths;
+
+ for (Uint32 i=0; i < cimNInstances.size(); i++)
+ {
+ try
+ {
+ resultObjectPaths = client->associatorNames(
+ nameSpace, cimNInstances[i].getPath(),
+ assocClass, resultClass, role, resultRole);
+
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ }
+ //
+ // Following exceptions will be caught in the Main method.
+ //
+ catch (CIMException &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("CIMException in enumerateAssociatorNames : ");
+ errorInfo.append(e.getMessage());
+ CIMException cimExp(e.getCode(), errorInfo);
+ throw cimExp;
+ }
+ catch (Exception &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("Exception in enumerateAssociatorNames : ");
+ errorInfo.append(e.getMessage());
+ Exception exp(errorInfo);
+ throw exp;
+ }
+ catch (...)
+ {
+ Exception exp("General Exception in enumerateAssociatorNames ");
+ throw exp;
+ }
+ }
+}
+/**
+ EnumerateInstanceRelatedInfo
+ This method enumerates instances, referances (by way of subrotine) and
+ associators (by way of subrotine.Exceptions are caught, modified and
+ re-thrown so that generic exception handling can be used in Main
+*/
+static void enumerateInstanceRelatedInfo(
+ TestModelWalkStressClient &tmsc,
+ CIMClient *client,
+ Array<CIMName> classNames,
+ CIMNamespaceName nameSpace,
+ pid_t clientPid,
+ String& clientLog,
+ String &clientId,
+ int status,
+ String &pidFile )
+{
+ Boolean deepInheritance = true;
+ Boolean localOnly = true;
+ Boolean includeQualifiers = false;
+ Boolean includeClassOrigin = false;
+ Array<CIMInstance> cimNInstances;
+
+ for (Uint32 i=0; i < classNames.size(); i++)
+ {
+ try
+ {
+ cimNInstances = client->enumerateInstances(
+ nameSpace, classNames[i], deepInheritance,
+ localOnly, includeQualifiers, includeClassOrigin);
+
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ }
+ //
+ // Following exceptions will be caught in the Main method.
+ //
+ catch (CIMException &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("CIMException thrown from ");
+ errorInfo.append("enumerateInstanceRelatedInfo, class = ");
+ errorInfo.append(classNames[i].getString());
+ errorInfo.append(" ");
+ errorInfo.append(e.getMessage());
+ CIMException cimExp(e.getCode(), errorInfo);
+ throw cimExp;
+ }
+ catch (Exception &e)
+ {
+ errorInfo.clear();
+ errorInfo.append("Exception thrown from ");
+ errorInfo.append("enumerateInstanceRelatedInfo, class = ");
+ errorInfo.append(classNames[i].getString());
+ errorInfo.append(" ");
+ errorInfo.append(e.getMessage());
+ Exception exp(errorInfo);
+ throw exp;
+ }
+ catch (...)
+ {
+ Exception exp("General Exception in EnumerateInstanceRelatedInfo ");
+ throw exp;
+ }
+
+ enumerateReferenceNames (tmsc, client, cimNInstances, nameSpace,
+ CIMName(), clientPid, clientLog, clientId, status, pidFile);
+ enumerateAssociatorNames (tmsc, client, cimNInstances, nameSpace,
+ CIMName(), clientPid, clientLog, clientId, status, pidFile);
+
+ if (verboseTest)
+ {
+ errorInfo.clear();
+ errorInfo.append("+++++ Successfully Done Instance Operations ");
+ errorInfo.append("on class = ");
+ errorInfo.append(classNames[i].getString());
+ tmsc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+ }
+
+}
+/**
+ EnumerateClassRelatedInfo
+ This method enumerates classes and instances (by way of subrotine)
+*/
+static void enumerateClassRelatedInfo(
+ TestModelWalkStressClient &tmsc,
+ CIMClient* client,
+ OptionManager &om,
+ Array<CIMNamespaceName> nameSpacesArray,
+ pid_t clientPid,
+ String& clientLog,
+ String &clientId,
+ int status,
+ String &pidFile)
+{
+ Array<CIMName> classNames;
+ String tmpClassName;
+
+ om.lookupValue("classname",tmpClassName);
+ if (tmpClassName != String::EMPTY)
+ {
+ classNames.append(CIMName(tmpClassName));
+ enumerateInstanceRelatedInfo(tmsc, client, classNames,
+ *nameSpacesArray.getData(), clientPid, clientLog, clientId,
+ status, pidFile);
+ }
+ else
+ {
+ Boolean deepInheritance = true;
+ CIMName className;
+ for (Uint32 i=0; i < nameSpacesArray.size();i++)
+ {
+ classNames = client->enumerateClassNames(nameSpacesArray[i],
+ className, deepInheritance);
+
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ enumerateInstanceRelatedInfo(tmsc, client, classNames,
+ nameSpacesArray[i], clientPid, clientLog, clientId, status,
+ pidFile );
+ }
+ }
+ if (verboseTest)
+ {
+ errorInfo.clear();
+ errorInfo.append("+++++ Successfully Enumerated classes ");
+ errorInfo.append("in Namespaces +++++");
+ tmsc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+}
+/**
+ MAIN
+*/
+
+int main(int argc, char** argv)
+{
+ OptionManager om;
+ TestModelWalkStressClient tmsc;
+ Uint32 validArg = 0;
+ struct OptionRow *newOptionsTable = 0;
+ Uint32 newOptionsCount = 0;
+ Uint32 cOptionCount = 0;
+
+ //
+ // Variables need to connect to server.
+ //
+ Boolean useSSL;
+ String host;
+ Uint32 portNumber = 0;
+ String portStr;
+ String userName;
+ String password;
+ String help;
+ Boolean connectedToHost = false;
+
+ //
+ // Variables needed to do loging and status checking.
+ //
+ String pidFile;
+ String clientId;
+ pid_t clientPid;
+ String clientLog, stopClient;
+ char pid_str[15];
+
+ //
+ // Number of times the command succeeded.
+ //
+ Uint32 successCount=0;
+
+ //
+ // Number of iterations after which logErrorPercentage() is called.
+ //
+ Uint32 iteration=0;
+
+ //
+ // Total number of times the command was executed.
+ //
+ Uint32 totalCount=0;
+
+ //
+ // timeout.
+ //
+ Uint32 timeout = 30000;
+
+ //
+ // This try block includes all the options gathering function.
+ //
+ try
+ {
+ //
+ // client specific options if any.
+ //
+ struct OptionRow *cOptionTable = 0;
+ newOptionsCount = cOptionCount;
+
+ try
+ {
+ //
+ // Generate new option table for this client using
+ // the OptionManager.
+ //
+
+ newOptionsTable = tmsc.generateClientOptions(cOptionTable,
+ cOptionCount,newOptionsCount);
+ validArg = tmsc.GetOptions(om, argc, argv, newOptionsTable,
+ newOptionsCount);
+ }
+ catch (Exception& e)
+ {
+ PEGASUS_STD(cerr) << argv[0] << ": " << e.getMessage()
+ << PEGASUS_STD(endl);
+ exit(1);
+ }
+ catch (...)
+ {
+ PEGASUS_STD(cerr) << argv[0] << ": Error in Options operation "
+ << PEGASUS_STD(endl);
+ exit(1);
+ }
+
+ verboseTest = om.isTrue("verbose");
+
+ om.lookupValue("username", userName);
+
+ om.lookupValue("password", password);
+
+ om.lookupIntegerValue("timeout",timeout);
+
+ useSSL = om.isTrue("ssl");
+
+ om.lookupValue("hostname",host);
+ om.lookupValue("port",portStr);
+
+ if (portStr.getCString())
+ {
+ sscanf (portStr.getCString (), "%u", &portNumber);
+ }
+
+ //
+ // Setting default ports.
+ //
+ if (!portNumber)
+ {
+ if (useSSL)
+ {
+ portNumber = 5989;
+ }
+ else
+ {
+ portNumber = 5988;
+ }
+ }
+
+ //
+ // default host is localhost.
+ //
+ if (host == String::EMPTY)
+ {
+ host = String("localhost");
+ }
+
+ //
+ // Signal Handling - SIGINT
+ //
+ signal(SIGINT, endTest);
+
+ om.lookupValue("clientid", clientId);
+
+ om.lookupValue("pidfile", pidFile);
+
+ clientPid = getpid();
+
+ om.lookupValue("clientlog", clientLog);
+
+ om.lookupValue("help", help);
+
+ }// end of option Try block
+ catch (Exception& e)
+ {
+ PEGASUS_STD(cerr) << argv[0] << ": " << e.getMessage()
+ << PEGASUS_STD(endl);
+ exit(1);
+ }
+ catch (...)
+ {
+ PEGASUS_STD(cerr) << argv[0] << ": Unknown Error gathering options "
+ << PEGASUS_STD(endl);
+ exit(1);
+ }
+
+ /* Checking whether the user asked for HELP Info...
+ if (om.valueEquals("help", "true"))
+ {
+ String header = "Usage ";
+ header.append(argv[0]);
+ header.append(" -parameters -n [namespace] -c [classname] ");
+ header.append(" -clientId [clientId] -pidFile [pidFile] ");
+ header.append(" -clientLog [clientLog]");
+ String trailer = "Assumes localhost:5988 if host not specified";
+ trailer.append("\nHost may be of the form name or name:port");
+ trailer.append("\nPort 5988 assumed if port number missing.");
+ om.printOptionsHelpTxt(header, trailer);
+ exit(0);
+ } */
+
+ try
+ {
+ //
+ // Timer Start.
+ //
+ tmsc.startTime();
+
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+
+ //
+ // connect the client.
+ //
+ CIMClient* client = new CIMClient();
+
+ sprintf(pid_str, "%d", clientPid);
+
+ stopClient = String::EMPTY;
+ stopClient.append(FileSystem::extractFilePath(pidFile));
+ stopClient.append("STOP_");
+ stopClient.append(pid_str);
+
+ //
+ // This loop executes till the client gets stop signal from
+ // controller.
+ //
+ while (!quit)
+ {
+ if (FileSystem::exists(stopClient))
+ {
+ if (verboseTest)
+ {
+ String mes("Ending client. ");
+ tmsc.errorLog(clientPid, clientLog, mes);
+ }
+ break;
+ }
+
+ if (!verboseTest)
+ {
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ freopen("nul","w",stdout);
+#else
+ freopen("/dev/null","w",stdout);
+#endif
+ }
+
+ if (!connectedToHost)
+ {
+ try
+ {
+ tmsc.connectClient( client, host, portNumber, userName,
+ password, useSSL, timeout, verboseTest);
+ connectedToHost = true;
+
+ //
+ // Client has successfully connected to server.
+ // update status if previously not Success.
+ //
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ }
+ catch (CannotConnectException)
+ {
+ status = CLIENT_UNKNOWN;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ connectedToHost = false;
+ }
+ catch (CIMException &e)
+ {
+ status = CLIENT_UNKNOWN;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ connectedToHost = false;
+ String mes(e.getMessage());
+ tmsc.errorLog(clientPid, clientLog, mes);
+ }
+ catch (Exception &e)
+ {
+ status = CLIENT_UNKNOWN;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ connectedToHost = false;
+ String mes(e.getMessage());
+ tmsc.errorLog(clientPid, clientLog, mes);
+ }
+ catch (...)
+ {
+ status = CLIENT_UNKNOWN;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ connectedToHost = false;
+ String mes("Error connencting to server in ModleWalk");
+ mes.append(" client ");
+ tmsc.errorLog(clientPid, clientLog,mes);
+ }
+ }/* end of if (!connectedToHost). */
+ iteration++;
+ totalCount++;
+ if (connectedToHost)
+ {
+ try
+ {
+ Array<CIMNamespaceName> nameSpacesArray;
+
+ //
+ // Enumerate all the namespaces here.
+ //
+ nameSpacesArray = getNameSpaces(
+ tmsc,
+ client,
+ om,
+ clientPid,
+ clientLog,
+ clientId,
+ status,
+ pidFile);
+
+ //
+ // Enumerate all qualifiers in the namespaces.
+ //
+ enumerateAllQualifiers(
+ tmsc,
+ client,
+ nameSpacesArray,
+ clientPid,
+ clientLog,
+ clientId,
+ status,
+ pidFile);
+
+ //
+ // Enumerate all the class related info here.
+ //
+ enumerateClassRelatedInfo(
+ tmsc,
+ client,
+ om,
+ nameSpacesArray,
+ clientPid,
+ clientLog,
+ clientId,
+ status,
+ pidFile);
+
+ successCount++;
+ }
+ //
+ // This specail catch block in needed so that we will know if
+ // the connenction was lost. We then connect on the next time
+ // through the loop.
+ //
+
+ catch (CannotConnectException)
+ {
+ status = CLIENT_UNKNOWN;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ connectedToHost = false;
+ }
+ catch (CIMException &cimE)
+ {
+ status = CLIENT_FAIL;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ String mes(cimE.getMessage());
+ tmsc.errorLog(clientPid, clientLog, mes);
+ }
+ catch (Exception &exp)
+ {
+ status = CLIENT_FAIL;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ String mes(exp.getMessage());
+ tmsc.errorLog(clientPid, clientLog, mes);
+ }
+ catch (...)
+ {
+ status = CLIENT_FAIL;
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ String mes("Unknown Error during ModelWalk Execution");
+ tmsc.errorLog(clientPid, clientLog, mes);
+ }
+
+ nextCheck = tmsc.checkTime();
+ if (nextCheck)
+ {
+ tmsc.logInfo(clientId, clientPid, status, pidFile);
+ nextCheck = false;
+ }
+
+ //
+ // If verbose is set, log success percentage for every 100
+ // iterations. If verbose is not set, log success percentage
+ // for every 10000 iterations.
+ //
+ if (verboseTest)
+ {
+ if (iteration == 100)
+ {
+ tmsc.logErrorPercentage(
+ successCount,
+ totalCount,
+ clientPid,
+ clientLog,
+ clientName);
+ iteration = 0;
+ }
+ }
+ else
+ {
+ if (iteration == 1000)
+ {
+ tmsc.logErrorPercentage(
+ successCount,
+ totalCount,
+ clientPid,
+ clientLog,
+ clientName);
+ iteration = 0;
+ }
+ }
+ }
+ } // end of while (!quit).
+ }
+ catch (Exception &exp)
+ {
+ String expStr("Exception in ModelWalk client, causing it to exit: ");
+ expStr.append(exp.getMessage());
+ tmsc.errorLog(clientPid, clientLog, expStr);
+
+ if (verboseTest)
+ {
+ PEGASUS_STD(cerr) << expStr.getCString() << PEGASUS_STD(endl);
+ }
+ }
+ catch (...)
+ {
+ String expStr("General Exception in ModelWalk, causing it to exit");
+ tmsc.errorLog(clientPid, clientLog, expStr);
+
+ if (verboseTest)
+ {
+ PEGASUS_STD(cerr) << expStr.getCString() << PEGASUS_STD(endl);
+ }
+ }
+
+//
+// One second delay before shutdown.
+//
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ sleep(1);
+#else
+ Sleep(1000);
+#endif
+ if (FileSystem::exists(stopClient))
+ {
+ //
+ // Remove STOP file here.
+ //
+ FileSystem::removeFile(stopClient);
+ }
+
+ if (verboseTest)
+ {
+ errorInfo.clear();
+ errorInfo.append("+++++ TestModelWalkStressClient Terminated ");
+ errorInfo.append("Normally +++++");
+ tmsc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+ return 0;
+}
diff --git a/test/StressTestClients/TestStressTestClient.cpp b/test/StressTestClients/TestStressTestClient.cpp
new file mode 100644
index 0000000..aa79810
--- /dev/null
+++ b/test/StressTestClients/TestStressTestClient.cpp
@@ -0,0 +1,417 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: Aruran (aruran.shanmug@in.ibm.com) & Melvin (msolomon@in.ibm.com),
+// IBM for PEP# 241
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include "TestStressTestClient.h"
+
+PEGASUS_USING_PEGASUS;
+PEGASUS_USING_STD;
+
+/** Constructor - Initializes the time variables and defines the Options
+ Table.
+*/
+TestStressTestClient::TestStressTestClient()
+{
+ startMilliseconds = 0;
+ nowMilliseconds = 0;
+ nextCheckupInMillisecs = 0;
+ static struct OptionRow testOptionsTable[] = {
+ {"namespace", "", false, Option::STRING, 0, 0, "namespace",
+ "specifies namespace to be used for the test"},
+
+ {"classname", "", false, Option::STRING, 0, 0, "classname",
+ "specifies classname to be used for the test"},
+
+ {"verbose", "false", false, Option::BOOLEAN, 0, 0, "verbose",
+ "If set, outputs extra information "},
+
+ {"help", "false", false, Option::BOOLEAN, 0, 0, "help",
+ "Prints help message with command line options "},
+
+ {"ssl", "false", false, Option::BOOLEAN, 0, 0, "ssl", "use SSL"},
+
+ {"username", "", false, Option::STRING, 0, 0, "username",
+ "Specifies user name"},
+
+ {"password", "", false, Option::STRING, 0, 0, "password",
+ "Specifies password"},
+
+ {"port", "", false, Option::STRING, 0, 0, "port",
+ "Port number on host"},
+
+ {"clientid", "", true, Option::STRING, 0, 0, "clientid",
+ "Client identification by controller"},
+
+ {"pidfile", "", true, Option::STRING, 0, 0, "pidfile",
+ "Client process log file"},
+
+ {"clientlog", "", true, Option::STRING, 0, 0, "clientlog",
+ "Client error log file"},
+
+ {"hostname", "", false, Option::STRING, 0, 0, "hostname",
+ "Host name"}
+ };
+ optionCount = sizeof(testOptionsTable) / sizeof(testOptionsTable[0]);
+ optionsTable = testOptionsTable;
+ }
+/**
+ OPTION MANAGEMENT
+*/
+
+/** GetOptions function - This function sets up the options from
+ testOptionsTable which is initialized through constructor
+ using the option manager.
+ const char* optionName;
+ const char* defaultValue;
+ int required;
+ Option::Type type;
+ char** domain;
+ Uint32 domainSize;
+ const char* commandLineOptionName;
+ const char* optionHelpMessage;
+*/
+int TestStressTestClient::GetOptions(
+ OptionManager& om,
+ int& argc,
+ char** argv,
+ OptionRow* newOptionsTable, Uint32 cOptionCount)
+{
+ char **argvv;
+ int counter = 0;
+ String argument = String::EMPTY;
+
+
+ //
+ // om.registerOptions(newOptionsTable, (const)cOptionCount);
+ //
+ om.registerOptions(newOptionsTable, cOptionCount);
+ argvv = argv;
+
+ //
+ // Following section is introduced to ignore options not
+ // required by a client.
+ //
+ for (int i = 1; i < argc; i++)
+ {
+ argument = String::EMPTY;
+ const char* arg = argv[i];
+
+ //
+ // Check for - option.
+ //
+ if (*arg == '-')
+ {
+ //
+ // Look for the option.
+ //
+ argument.append(arg + 1);
+ const Option* option = om.lookupOption(argument);
+
+ //
+ // Get the option argument if any.
+ //
+ if (option)
+ {
+ argvv[++counter]=argv[i];
+ if (option->getType() != Option::BOOLEAN)
+ {
+ if (i + 1 != argc)
+ {
+ argvv[++counter] = argv[++i];
+ }
+ }
+ }
+ }
+ }
+ ++counter;
+ om.mergeCommandLine(counter, argvv);
+ om.checkRequiredOptions();
+ return counter;
+}
+
+/** This method is used by clients to register client specific required
+ options to the option table. All these options are taken as mandatory one.
+*/
+OptionRow *TestStressTestClient::generateClientOptions(
+ OptionRow* clientOptionsTable,
+ Uint32 clientOptionCount,
+ Uint32& totalOptions)
+{
+
+ Uint32 currOptionCount = 0;
+ static struct OptionRow *newOptionsTable = 0;
+
+ totalOptions = optionCount + clientOptionCount;
+
+ newOptionsTable = new struct OptionRow[totalOptions];
+
+ for (; currOptionCount < optionCount; currOptionCount++)
+ {
+ newOptionsTable[currOptionCount] = optionsTable[currOptionCount];
+ }
+ for (Uint32 i =0; i < clientOptionCount; i++)
+ {
+ newOptionsTable[currOptionCount] = clientOptionsTable[i];
+ currOptionCount++;
+ }
+ return newOptionsTable;
+}
+
+/** This method is used by the clients to log information which are required
+ for controller reference. It logs the information with Client ID and
+ status of the client in the PID File log file.
+*/
+void TestStressTestClient::logInfo(
+ String clientId,
+ pid_t clientPid,
+ int clientStatus,
+ String &pidFile)
+{
+ String line, searchString, subLine;
+ int indx = 0;
+ char pid_str[15];
+ char status_str[15];
+ char time_str[32];
+
+ searchString.append(clientId.getCString());
+
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ int offset = 2;
+#else
+ int offset = 1;
+#endif
+
+ Uint32 whileCount = 0;
+
+ //
+ // Get current time for time stamp
+ //
+ nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+
+ sprintf(pid_str, "%d", clientPid);
+ sprintf(status_str, "%d", clientStatus);
+ sprintf(time_str, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
+ nowMilliseconds);
+
+ fstream pFile(pidFile.getCString(),ios::in|ios::out);
+
+ Boolean addClient= false;
+
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ if (pFile.is_open())
+#else
+ if (pFile)
+#endif
+ {
+ while(!pFile.eof())
+ {
+ whileCount++;
+ GetLine (pFile,line);
+ indx=line.find(':');
+ if (indx > 0)
+ {
+ subLine.append(line.subString(0, indx));
+ }
+ if (String::compare(subLine, searchString) == 0)
+ {
+ long pos;
+ addClient = true;
+ pos = pFile.tellp();
+ pFile.seekp(pos - line.size()-offset);
+ String newLine = String(clientId.getCString());
+ newLine.append("::");
+ newLine.append(pid_str);
+ newLine.append("::");
+ newLine.append(status_str);
+ newLine.append("::");
+ newLine.append(time_str);
+ if (line.size() > newLine.size())
+ {
+ Uint32 jSize = line.size() - newLine.size();
+ pFile.write(newLine.getCString(),newLine.size());
+ for (Uint32 i =0;i<jSize;i++)
+ {
+ pFile.write(" ",1);
+ }
+ }
+ else
+ {
+ pFile.write(newLine.getCString(),newLine.size());
+ }
+ break;
+ }
+ subLine.clear();
+ line.clear();
+ }
+ if(!addClient)
+ {
+ pFile.close();
+ fstream pFile(pidFile.getCString(),ios::out|ios::app);
+ pFile<<clientId<<"::"<<clientPid<<"::"<<clientStatus<<"::"
+ <<time_str<<"\n";
+ }
+ }
+ pFile.close();
+}
+
+/** This method is used to take the client process start time.*/
+void TestStressTestClient::startTime()
+{
+ startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+ nowMilliseconds = startMilliseconds;
+}
+
+/** This method is used to check the time stamp for logging information about
+ the success or failure.
+*/
+Boolean TestStressTestClient::checkTime()
+{
+ nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+
+ if (nowMilliseconds >= nextCheckupInMillisecs)
+ {
+ nextCheckupInMillisecs = (Uint64)convertmin2millisecs(CHECKUP_INTERVAL)
+ + nowMilliseconds;
+ return true;
+ }
+ return false;
+}
+
+/** This method is used to log the information about the client's success or
+ failure percentage at a specific interval of time.
+*/
+void TestStressTestClient::logErrorPercentage(
+ Uint32 successCount,
+ Uint32 totalCount,
+ pid_t clientPid,
+ String &clientLog,
+ char client[])
+{
+ Uint32 successPercentage, errorPercentage;
+ successPercentage = (successCount/totalCount)*100;
+ errorPercentage = 100 - successPercentage;
+
+ //
+ // loging details here
+ //
+ ofstream errorLog_File(clientLog.getCString(), ios::app);
+ errorLog_File<<client<<" PID#"<<clientPid<<" ran "<<totalCount
+ <<" times with a "<<errorPercentage<<"% failure"<<"\n";
+ errorLog_File.close();
+}
+
+/** This method is used to log the informations of client logs to the client
+ log file.
+*/
+void TestStressTestClient::errorLog(
+ pid_t clientPid,
+ String &clientLog,
+ String &message)
+{
+ //
+ // loging details here .
+ //
+ ofstream errorLog_File(clientLog.getCString(), ios::app);
+ errorLog_File<<" PID#"<<clientPid<<"::"<<message<<"\n";
+ errorLog_File.close();
+}
+
+/** This method handles the SSLCertificate verification part. */
+static Boolean verifyCertificate(SSLCertificateInfo &certInfo)
+{
+ //
+ // Add code to handle server certificate verification.
+ //
+ return true;
+}
+
+/** This method is used by the clients to connect to the server. If useSSL is
+ true then an SSL connection will be atemped with the userName and passWord
+ that is passed in. Otherwise connection will be established using
+ localhost. All parameters are required.
+*/
+void TestStressTestClient::connectClient(
+ CIMClient *client,
+ String host,
+ Uint32 portNumber,
+ String userName,
+ String password,
+ Boolean useSSL,
+ Uint32 timeout,
+ Boolean verboseTest)
+{
+ if (useSSL)
+ {
+ //
+ // Get environment variables.
+ //
+ const char* pegasusHome = getenv("PEGASUS_HOME");
+
+ String trustpath = FileSystem::getAbsolutePath(
+ pegasusHome, PEGASUS_SSLCLIENT_CERTIFICATEFILE);
+
+ String randFile = String::EMPTY;
+
+#ifdef PEGASUS_SSL_RANDOMFILE
+ randFile = FileSystem::getAbsolutePath(
+ pegasusHome,
+ PEGASUS_SSLCLIENT_RANDOMFILE);
+#endif
+
+ SSLContext sslContext(
+ trustpath, verifyCertificate, randFile);
+ if (verboseTest)
+ {
+ cout << "connecting to " << host << ":"
+ << portNumber << " using SSL"
+ << endl;
+ }
+ client->connect (host, portNumber, sslContext, userName, password);
+ } /* useSSL. */
+ else
+ {
+ if (verboseTest)
+ {
+ cout << "Connecting to " << host << ":" << portNumber
+ << endl;
+ }
+ client->connect (host, portNumber, userName, password);
+ }
+ if (verboseTest)
+ {
+ cout << "Client Connected" << endl;
+ }
+}
diff --git a/test/StressTestClients/TestStressTestClient.h b/test/StressTestClients/TestStressTestClient.h
new file mode 100644
index 0000000..9a23231
--- /dev/null
+++ b/test/StressTestClients/TestStressTestClient.h
@@ -0,0 +1,184 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: Aruran (aruran.shanmug@in.ibm.com) & Melvin (msolomon@in.ibm.com),
+// IBM for PEP# 241
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#ifndef TestStressTestClient_h
+#define TestStressTestClient_h
+
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Common/Constants.h>
+#include <Pegasus/Common/TLS.h>
+#include <Pegasus/Common/CIMName.h>
+#include <Pegasus/Common/OptionManager.h>
+#include <Pegasus/Common/FileSystem.h>
+#include <Pegasus/Common/Exception.h>
+#include <Pegasus/Common/XmlWriter.h>
+#include <Pegasus/Client/CIMClient.h>
+#include <Pegasus/Common/Signal.h>
+#include <Pegasus/Common/Exception.h>
+#include <Pegasus/Common/TimeValue.h>
+#include <signal.h>
+#include "Linkage.h"
+
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ // DWORD etc.
+ #include <windows.h>
+ typedef DWORD pid_t;
+ // getpid() and others.
+ #include <process.h>
+#elif !defined(PEGASUS_OS_OS400)
+ #include <unistd.h>
+#endif
+
+#ifdef PEGASUS_PLATFORM_SOLARIS_SPARC_CC
+ #include <iostream.h>
+#endif
+
+#define SIXTYSECONDS 60
+#define MILLISECONDS 1000
+#define CHECKUP_INTERVAL 0.8
+#define convertmin2millisecs(x) ((x * SIXTYSECONDS * MILLISECONDS))
+
+PEGASUS_NAMESPACE_BEGIN
+
+/**
+ StressTest Client Status types.
+*/
+enum CStatus
+{
+ CLIENT_PASS,
+ CLIENT_FAIL,
+ CLIENT_UNKNOWN
+};
+
+/** The TestStressTestClient class holds the common functionality for all the
+ stress test clients.
+*/
+class PEGASUS_STRESSTESTCLIENT_LINKAGE TestStressTestClient
+{
+public:
+ /**
+ Constructor.
+ */
+ TestStressTestClient();
+
+ /**
+ This method is used to get all the options that are passed through
+ command line.
+ */
+ int GetOptions(
+ OptionManager& om,
+ int& argc,
+ char** argv,
+ OptionRow* clientOptionsTable,
+ Uint32 clientOptionCount);
+
+ /**
+ This method is used by clients to register client specific required
+ options to the option table. All these options are taken as mandatory
+ one.
+ */
+ OptionRow* generateClientOptions(
+ OptionRow* clientOptionsTable,
+ Uint32 clientOptionCount,
+ Uint32& totalOptionCount);
+
+ /**
+ This method is used by the clients to connect to the server. If useSSL
+ is true then an SSL connection will be atemped with the userName and
+ passWord that is passed in. If localConnection is true a connectLocal
+ connection will be attempted. All parameters are required.
+ */
+ void connectClient(
+ CIMClient *client,
+ String host,
+ Uint32 portNumber,
+ String userName,
+ String passWord,
+ Boolean useSSL,
+ Uint32 timeout,
+ Boolean verboseTest);
+
+ /**
+ This method is used by the clients to log information which are
+ required for controller reference. It logs the inofrmation with
+ Client ID and status of the client in the PID File log file.
+ */
+ void logInfo(
+ String clientId,
+ pid_t clientPid,
+ int clientStatus,
+ String &pidFile);
+
+ /**
+ This method is used to take the client process start time.
+ */
+ void startTime();
+
+ /**
+ This method is used to check the time stamp for logging information
+ about the success or failure.
+ */
+ Boolean checkTime();
+
+ /**
+ This method is used to log the information about the client's success
+ or failure percentage at a specific interval of time.
+ */
+ void logErrorPercentage(
+ Uint32 successCount,
+ Uint32 totalCount,
+ pid_t clientPid,
+ String &clientLog,
+ char client[]);
+
+ /**
+ This method is used to log the informations of client logs to the
+ client log file.
+ */
+ void errorLog(pid_t clientPid, String &clientLog, String &message);
+
+ /**
+ Timer details.
+ */
+ Uint64 startMilliseconds;
+ Uint64 nowMilliseconds;
+ Uint64 nextCheckupInMillisecs;
+ struct OptionRow *optionsTable;
+ Uint32 optionCount;
+};
+PEGASUS_NAMESPACE_END
+#endif /* TestStressTestClient_h */
diff --git a/test/StressTestClients/WrapperStressClient/Makefile b/test/StressTestClients/WrapperStressClient/Makefile
new file mode 100644
index 0000000..88093d6
--- /dev/null
+++ b/test/StressTestClients/WrapperStressClient/Makefile
@@ -0,0 +1,59 @@
+#//%2006////////////////////////////////////////////////////////////////////////
+#//
+#// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+#// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+#// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation, The Open Group.
+#// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; Symantec Corporation; The Open Group.
+#//
+#// Permission is hereby granted, free of charge, to any person obtaining a copy
+#// of this software and associated documentation files (the "Software"), to
+#// deal in the Software without restriction, including without limitation the
+#// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+#// sell copies of the Software, and to permit persons to whom the Software is
+#// furnished to do so, subject to the following conditions:
+#//
+#// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+#// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+#// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+#// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+#// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+#// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#//
+#//==============================================================================
+ROOT = $(PEGASUS_ROOT)
+
+DIR = test/StressTestClients/WrapperStressClient
+
+include $(ROOT)/mak/config.mak
+
+LIBRARIES = \
+ TestStressTestClient \
+ pegcommon
+
+PROGRAM = TestWrapperStressClient
+
+SOURCES = \
+ TestWrapperStressClient.cpp
+
+ifneq ($(PEGASUS_PLATFORM),ZOS_ZSERIES_IBM)
+ ifneq ($(OS),HPUX)
+ ifdef PEGASUS_ENABLE_SLP
+ LIBRARIES += pegslp
+ endif
+ endif
+endif
+
+include $(ROOT)/mak/program.mak
+
+tests:
+
+poststarttests:
+
diff --git a/test/StressTestClients/WrapperStressClient/TestWrapperStressClient.cpp b/test/StressTestClients/WrapperStressClient/TestWrapperStressClient.cpp
new file mode 100644
index 0000000..53107de
--- /dev/null
+++ b/test/StressTestClients/WrapperStressClient/TestWrapperStressClient.cpp
@@ -0,0 +1,360 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: Melvin, IBM (msolomon@in.ibm.com) for PEP# 241
+//
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include "../TestStressTestClient.h"
+
+PEGASUS_USING_PEGASUS;
+PEGASUS_USING_STD;
+
+class TestWrapperStressClient : public TestStressTestClient
+{
+};
+
+Boolean quit = false;
+Boolean nextCheck = false;
+String errorInfo;
+char thisClient[] = "WrapperStressClient";
+
+/**
+ Signal handler for SIGALARM.
+ @param signum - the alarm identifier
+ */
+void endTest(int signum)
+{
+ cout<<"Recieved interupt signal SIGINT!\n"<<endl;
+ quit = true;
+}
+
+/**
+ MAIN
+*/
+int main(int argc, char** argv)
+{
+ OptionManager om;
+ TestWrapperStressClient wc;
+ pid_t clientPid = getpid();
+ Uint32 validArg = 0;
+ Boolean verboseTest;
+
+ //
+ // Varriables needed for loging and status checking.
+ //
+ String clientId;
+ String pidFile;
+ String clientLog, stopClient;
+ char pid_str[15];
+ int status = CLIENT_UNKNOWN;
+
+ //
+ // Number of times the client command succeeded.
+ //
+ Uint32 successCount = 0;
+
+ //
+ // Number of iterations after which logErrorPercentage() is called.
+ //
+ Uint32 iteration = 0;
+
+ //
+ // Total number of times the client command was executed.
+ //
+ Uint32 totalCount = 0;
+
+ //
+ // Variables needed for Command operation.
+ //
+ String command;
+
+ String options;
+ String help;
+
+ try
+ {
+ struct OptionRow *newOptionsTable = 0;
+ Uint32 newOptionsCount;
+
+ struct OptionRow cOptionTable[] =
+ {
+ {"clientname", "", true, Option::STRING, 0, 0, "clientname",
+ "Client name" },
+
+ {"options", "", true, Option::STRING, 0, 0, "options",
+ "Corresponding Client program's options" }
+ };
+
+ Uint32 cOptionCount = sizeof(cOptionTable) / sizeof(cOptionTable[0]);
+ newOptionsCount = cOptionCount;
+
+ try
+ {
+ //
+ // Generate new option table for this client using OptionManager
+ //
+ newOptionsTable = wc.generateClientOptions(
+ cOptionTable,
+ cOptionCount,
+ newOptionsCount);
+ validArg = wc.GetOptions(
+ om,
+ argc,
+ argv,
+ newOptionsTable,
+ newOptionsCount);
+ }
+ catch (Exception& e)
+ {
+ cerr << argv[0] << ": " << e.getMessage() << endl;
+ exit(1);
+ }
+ catch (...)
+ {
+ cerr << argv[0] << ": Error in Options operations "<< endl;
+ exit(1);
+ }
+
+ verboseTest = om.isTrue("verbose");
+
+ om.lookupValue("clientid", clientId);
+
+ om.lookupValue("pidfile", pidFile);
+
+ om.lookupValue("clientlog", clientLog);
+
+ om.lookupValue("clientname", command);
+
+ om.lookupValue("options", options);
+
+ om.lookupValue("help", help);
+ } /** end of option Try block. */
+ catch (Exception& e)
+ {
+ cerr << argv[0] << ": " << e.getMessage() <<endl;
+ exit(1);
+ }
+ catch (...)
+ {
+ cerr << argv[0] << ": Unknown Error gathering options "
+ << "in Wrapper Client " << endl;
+ exit(1);
+ }
+
+ /** Checking whether the user asked for HELP Info...
+ if (om.valueEquals("help", "true"))
+ {
+ String header = "Usage ";
+ header.append(argv[0]);
+ header.append(" -parameters -clientName [clientName]
+ header.append(" -options [options] -clientid [clientId] ");
+ header.append(" -pidfile [pidFile] -clientlog [clientLog]");
+ String trailer = "Assumes localhost:5988 if host not specified";
+ trailer.append("\nHost may be of the form name or name:port");
+ trailer.append("\nPort 5988 assumed if port number missing.");
+ om.printOptionsHelpTxt(header, trailer);
+ exit(0);
+ }
+ */
+
+ try
+ {
+ if (options.getCString())
+ {
+ command.append(" " + options);
+ }
+ if (verboseTest)
+ {
+ errorInfo.append("client command : ");
+ errorInfo.append(command);
+ wc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+
+ //
+ // Signal Handling - SIGINT.
+ //
+ signal(SIGINT, endTest);
+
+ //
+ // Timer Start.
+ //
+ wc.startTime();
+
+ wc.logInfo(clientId, clientPid, status, pidFile);
+ sprintf(pid_str, "%d", clientPid);
+
+ stopClient = String::EMPTY;
+ stopClient.append(FileSystem::extractFilePath(pidFile));
+ stopClient.append("STOP_");
+ stopClient.append(pid_str);
+
+ //
+ // This loop executes till the client gets stop signal from
+ // controller.
+ //
+ while (!quit)
+ {
+ if (FileSystem::exists(stopClient))
+ {
+ if (verboseTest)
+ {
+ String mes("Ending client. ");
+ wc.errorLog(clientPid, clientLog, mes);
+ }
+ break;
+ }
+
+ if (!verboseTest)
+ {
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ freopen("nul","w",stdout);
+#else
+ freopen("/dev/null","w",stdout);
+#endif
+ }
+
+ int i = system(command.getCString());
+
+ iteration++;
+ totalCount++;
+ switch (i)
+ {
+ case 0:
+ if (status != CLIENT_PASS)
+ {
+ status = CLIENT_PASS;
+ wc.logInfo(clientId, clientPid, status, pidFile);
+ }
+ successCount++;
+ break;
+
+ case 1:
+ status = CLIENT_UNKNOWN;
+ wc.logInfo(clientId, clientPid, status, pidFile);
+ break;
+
+ default:
+ status = CLIENT_FAIL;
+ wc.logInfo(clientId, clientPid, status, pidFile);
+ break;
+ }
+
+ nextCheck = wc.checkTime();
+ if (nextCheck)
+ {
+ wc.logInfo(clientId, clientPid, status, pidFile);
+ nextCheck = false;
+ }
+
+ //
+ // If verbose is set, log success percentage for every 100
+ // iterations. If verbose is not set, log success percentage
+ // for every 1000 iterations.
+ //
+ if (verboseTest)
+ {
+ if (iteration == 100)
+ {
+ wc.logErrorPercentage(
+ successCount,
+ totalCount,
+ clientPid,
+ clientLog,
+ thisClient);
+ iteration = 0;
+ }
+ }
+ else
+ {
+ if (iteration == 1000)
+ {
+ wc.logErrorPercentage(
+ successCount,
+ totalCount,
+ clientPid,
+ clientLog,
+ thisClient);
+ iteration = 0;
+ }
+ }
+ } /** end of while(!quit). */
+ } /** end of command execution try block. */
+ catch (Exception &exp)
+ {
+ String expStr("Exception in WrapperClient causing it to exit: ");
+ expStr.append(exp.getMessage());
+ wc.errorLog(clientPid, clientLog, expStr);
+
+ if (verboseTest)
+ {
+ cerr << expStr.getCString() << endl;
+ }
+ }
+ catch (...)
+ {
+ String expStr("General Exception in WrapperClient causing it to exit");
+ wc.errorLog(clientPid, clientLog, expStr);
+
+ if (verboseTest)
+ {
+ cerr << expStr.getCString() << endl;
+ }
+ }
+
+//
+// second delay before shutdown.
+//
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ sleep(1);
+#else
+ Sleep(1000);
+#endif
+
+ if(FileSystem::exists(stopClient))
+ {
+ //
+ // Remove STOP file here.
+ //
+ FileSystem::removeFile(stopClient);
+ }
+ if (verboseTest)
+ {
+ errorInfo.append(
+ "++++ TestWrapperStressClient Terminated Normally +++++");
+ wc.errorLog(clientPid, clientLog, errorInfo);
+ errorInfo.clear();
+ }
+ return 0;
+}
diff --git a/test/StressTestController/Makefile b/test/StressTestController/Makefile
new file mode 100644
index 0000000..b19207f
--- /dev/null
+++ b/test/StressTestController/Makefile
@@ -0,0 +1,52 @@
+#//%2006////////////////////////////////////////////////////////////////////////
+#//
+#// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+#// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+#// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation, The Open Group.
+#// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; Symantec Corporation; The Open Group.
+#//
+#// Permission is hereby granted, free of charge, to any person obtaining a copy
+#// of this software and associated documentation files (the "Software"), to
+#// deal in the Software without restriction, including without limitation the
+#// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+#// sell copies of the Software, and to permit persons to whom the Software is
+#// furnished to do so, subject to the following conditions:
+#//
+#// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+#// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+#// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+#// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+#// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+#// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#//
+#//==============================================================================
+ROOT = $(PEGASUS_ROOT)
+
+DIR = test/StressTestController
+include $(ROOT)/mak/config.mak
+
+LOCAL_DEFINES = -DSTRESSTEST_DEFAULTCFGDIR=\"$(ROOT)/$(DIR)/\"
+
+LIBRARIES = \
+ pegcliutils \
+ peggetoopt \
+ pegclient \
+ pegcommon
+
+
+PROGRAM = TestStressTestController
+SOURCES = StressTestControllerException.cpp \
+ StressTestControllerMain.cpp \
+ StressTestController.cpp
+
+include $(ROOT)/mak/program.mak
+
+poststarttests:
diff --git a/test/StressTestController/README b/test/StressTestController/README
new file mode 100644
index 0000000..ce0abef
--- /dev/null
+++ b/test/StressTestController/README
@@ -0,0 +1,539 @@
+===============================================================================
+Please See PEP# 241 for more details on Open Pegasus Stress Tests:
+===============================================================================
+
+Open Pegasus stress tests are expected to exert excessive loads on the CIM
+server. The main intent of these tests are to see how fast, or whether, we can
+get the CIM server to crash or hang. These tests are designed to allow some
+flexibility in adjusting the desired stress level on the CIM server.
+
+===============================================================================
+Table of Contents:
+===============================================================================
+1.0 Execution model assumptions
+2.0 OpenPegasus Stress Test Overview
+ 2.1 TestStressTestController
+ 2.2 Stress Test Clients
+ 2.3 The Stress Test Configuration File
+3.0 Default Values
+4.0 Running a Stress Test using default values
+5.0 Running the new "stresstest" target
+6.0 Stress Test Logs
+7.0 Stress Test Errors
+8.0 Other Considerations
+===============================================================================
+
+*******************************************************************************
+1.0 Execution model assumptions:
+===============================================================================
+ 1.1 The proposed client-side functionality concerning stress test will be
+ tested only on Windows and Linux. Note, that the CIM server that is
+ being stressed can be running on any of the OpenPegasus supported
+ operating system.
+
+ 1.2 The CIM server that is being stress tested is expected but not required
+ to be running on a different system than the stress clients. This is
+ mainly to isolate the CIM server that is under stress.
+
+ 1.3 ALL OF THE PROPOSED STRESS TEST CLIENTS INVOKED BY A GIVEN EXECUTION OF
+ THE "TestStressTestController" ARE EXPECTED TO BE STRESS TESTING THE SAME
+ CIMSERVER.
+
+===================================================================i===========
+DIAGNOSIS OF CIM SERVER HANGS OR CRASHES CAUSED BY THE STRESS TESTS ARE
+EXPECTED TO BE DONE USING ALREADY EXISTING DEBUGGING AND TRACING TECHNIQUES
+OR TOOLS.
+===============================================================================
+
+*******************************************************************************
+2.0 OpenPegasus Stress Test Overview:
+===============================================================================
+ OpenPegasus Stress Test will be comprised of three major components, as
+ follows:
+
+
+ 1. TestStressTestController
+ Command that invokes one or more of the Stress Test Clients.
+
+ 2. Stress Test Clients.
+ Client Programs that may contain one or more of the CIM Operation(s).
+
+ 3. Stress Test Configuration.
+ A flat file containing test configuration information.
+
+ The "stressTestController" will read the configuration file and then,
+ invoke the "Stress Test Client" instances specified in the "Stress Test
+ Configuration". Each of the client instances will be a separate process.
+ These Clients will in turn connect to the same CIM Server and perform
+ their respective operations concurrently.
+
+ 2.1 TestStressTestController:
+ =====================
+ This command can be run using the following options:
+ (Usage information may be displayed using "--help" option)
+
+ TestStressTestController [ -s ] [ -h hostname ] [ -p portnumber ]
+ [ -u username ] [ -w password ] [ --help ]
+ [ --version ] [ --verbose ] [<config_filename>]
+
+ Options :
+ -h - Connect to CIM Server on specified hostname
+ --help - Display this help message
+ -p - Connect to CIM Server on specified portnumber
+ -s - Use SSL protocol between 'stressTestController' client
+ and the CIM Server
+ -u - Connect to CIM Server using the specified username
+ --version - Display CIM Server version number
+ --verbose - Display verbose information
+ -w - Connect to CIM Server using the specified password
+
+ Operands :
+ <config_filename>
+ - Specifies the name of the configuration file that is
+ to be used for the tests.
+
+ 2.1.1 The user may specify the name of the configuration file that is to be
+ used for the tests. When a configuration file is not specified at
+ command line, then the TeststressTestController command will use the
+ default configuration file if it exists, otherwise take the default
+ values hard coded in the TestStressTestcontroller.
+
+ 2.1.2 This command will also verify the validity of the configuration values
+ specified in the configuration file.
+
+ 2.1.3 This command will invoke one or more of the Stress Test Clients
+ specified below.
+
+ 2.1.4 This command will end for any of the following reasons:
+ - When "Duration" as specified in the Stress Test configuration file
+ has elapsed.
+ - If the specified configuration file cannot be found in the
+ configuration directory.
+ - If the configuration file has any invalid parameter or value.
+ - A persistent failure in one (or more) of the Stress Test Clients.
+ - The configuration can be setup to allow some margin of client
+ failures. By default, any client failure will be reported
+ and result in termination of the stress test
+ (this corresponds to a ToleranceLevel of 0%).
+
+ 2.1.5 When the command ends, it will as part of its cleanup also end
+ all the stress clients that it had originally started.
+
+ 2.1.6 All the options specified here on the command line will have
+ precedence over similar parameters specified in the configuration
+ file.
+
+ 2.1.7 Log files for the controller can be found in
+ $PEGASUS_HOME/test/StressTestController/log/ and will be named as
+ "<controller_pid>_stressTest_<DDMMYYhhmmss>.log "
+ where,
+ "DD" denotes the day.
+ "MM" denotes the month.
+ "YY" denotes the year.
+ "hh" denotes the hour.
+ "mm" denotes the minutes.
+ "ss" denotes the seconds.
+ "controller-pid" denotes the pid of the stressTestController
+
+ 2.1.8 Log file for the clients intiated by a controller can be found in
+ $PEGASUS_HOME/test/StressTestController/log/ and will be named as
+ <controller-pid>_StressTestClients.log
+ where,
+ "controller-pid" denotes the pid of the stressTestController
+
+ 2.2 Stress Test Clients:
+ ====================
+
+ The following table lists the Stress Test Clients and the associated CIM
+ Operations that each of these clients will perform on the CIM Server.
+ These clients once started will run repeatedly until stopped by the
+ stressTestController command. The expected stress factor imposed on the
+ CIM server is directly proportional to the number of client instances
+ running concurrently against the same CIM Server.
+
+ STRESS TEST CLIENTS DESCRIPTION
+
+ TestModelWalkStressClient For all the detectable namespaces this
+ client will perform an enumeration of
+ all Classes, Instances, References,
+ Associators & Qualifiers.
+
+ TestWrapperStressClient This is a wrapper client that will allow
+ existing clients or programs to be
+ existing clients or programs to be
+ executed. The intended client program
+ that is expected to be executed must
+ be specified in the configuration file
+ when using this client. The client program
+ must ensure that it connect to the
+ correct cimserver.
+ For example, this client can be used to
+ run pegasus CLI's to stress test the CIM
+ server. Also note that the "CLI" command
+ uses -l option to set the hostname where the
+ CIMServer is running.
+ Please refer to section 2.3.8(A Sample
+ Configuration File) for an example.
+
+ Note:
+ The above list of stress test Clients can grow as needed.
+ Please see PEP# 241 for possible future "Stress Test Clients":
+
+ 2.2.1 Stress Test Clients will Connect to the CIM Server running on the
+ specified hostname. However, if the hostname is not specified then
+ the client will attempt to connect with the CIM server on the same
+ system the client is invoked on.
+
+ 2.2.2 "Stress Test Clients" on completion or failure of its operation as
+ specified above will continue to repeat the operations until stopped
+ by the "TestStressTestController".
+
+ 2.3 The Stress Test Configuration File:
+ ===================================
+
+ 2.3.1 The default configuration filename for the stress test will be named
+ as "default_stresstest.conf".
+
+ 2.3.2 The user may specify the name of the configuration file that is to be
+ used for the tests.
+
+ 2.3.3 Default configuration file will be kept in
+ $PEGASSUS_ROOT/test/StressTestController/ directory.
+
+ 2.3.4 The Configuration file can contain the following common values that
+ would in turn provide the factors required for the stress tests:
+
+ 1. Duration of Tests.
+ - Duration in minutes all the .Stress Test Client. are to be run.
+ 2. HostName
+ - Host name or IP address of the system where the CIM server is
+ expected to be running.
+ 3. Port.
+ - Specifies Port number. The default port is 5988.
+ 4. Number of Clients.
+ - Number of concurrent clients.
+ 5. Name Space.
+ - Name space that will be utilized by the Stress Test Clients.
+ 6. Class Name.
+ - Name of the existing class that will be utilized by the Stress
+ Test Clients.
+ 7. SSL.
+ - Use SSL protocol between Stress Client and the CIM Server.
+ 8. UserName.
+ - User name that the Stress Test Clients will use to connect to
+ the server.
+ 9. Password.
+ - Password that is associated to the user name.
+ 10. ToleranceLevel.
+ - This represents the percentage of the started "Stress Test
+ client" that can be allowed to fail in every one minute
+ interval without resulting in the termination of the stress
+ tests.
+
+ NOTE:
+ Any reported client failure in a one minute interval corresponds
+ to a "failure status" for that interval. The default is 0%,
+ which means no failures are allowed, or any failures will result
+ in termination of the stress test.
+
+ 11. ClientDuration.
+ - Specifies duration in minutes for the corresponding stress
+ client before it should be stopped.
+ 12. ClientWait.
+ - Specifies waiting period in minutes before the corresponding
+ stress client is re-started again. "ClientDuration" when used
+ without "ClientWait" will not be re-run. "ClientWait" will
+ only apply when used with "ClientDuration".
+ 13. ClientName.
+ - The name of the Client program that will be used by a
+ TestWrapperStressClient instance.
+ 14. Options.
+ - The options that are desired for the corresponding Client
+ program that will be used by a TestWrapperStressClient.
+
+ 2.3.5 Instances of the Clients may also have unique configurable values.
+ Unique values can be specified for each instance in the
+ configuration file as shown in the Sample Configuration File below.
+ If any of the above parameters are repeated for a client instance,
+ then that particular instance(s) will utilize the new value.
+
+ 2.3.6 Parameters "ClientName" and "Options" are only used for
+ "TestWrapperStressClient".
+
+ 2.3.7 The parameter "Hostname" will have to be the same for all the
+ Clients.
+
+ NOTE:
+ - Options or values specific for each client or instance must be placed
+ after the corresponding client or instance. Otherwise, the order of
+ the configuration variables in the configuration file is not
+ important.
+ - When using a Client program like a "CLI" or any other "clients"
+ with the "TestWrapperStressClient", ensure that options associated
+ to the Client program will connect to the same CIM Server.
+
+ Example:
+ [clientname="CLI",options="niall -l <hostname>"]
+
+ - Running without a failure implies that the client is communicating
+ with the CIMServer and has recieved responses other than an
+ exception or a CIMError.
+
+ 2.3.8 A Sample Configuration File:
+ ===========================
+
+ #Machine Host of Server to be tested
+ #If left blank then default is the local host.
+ Hostname=narten
+
+ # Total Duration of the Stress Client Test set as 300 minutes.
+ Duration=300
+
+ # Tolerance level in percentage
+ ToleranceLevel=0
+
+ # Number of Client instances
+ # The format for running a client program:
+ # <client program name>=<number of instances of clients>
+ # [option1=<data1>, option2=<data2>, option3=<data3>, ..... ]
+ #
+ # specify all the options for a Client instance or instances within
+ # a square bracket "[ .... ]".
+ #
+ #
+ # TestWrapperStressClient can only have the parameters "ClientName"
+ # and "Options". All other options will be ignored.
+ # [ClientName=<ClientProgram>,Options=<actual options for Client>]
+
+ ModelWalkStressClient=1
+ [NameSpace=/root/cimv2,ClassName=CIM_door,ClientDuration=60,ClientWait=10]
+ ModelWalkStressClient=5
+ WrapperStressClient=2
+ [ClientName=CLI,Options="-l narten niall"]
+ WrapperStressClient=10
+ [ClientName=CLI,Options="-l narten ei pg_computersystem"]
+ WrapperStressClient=5
+ [ClientName=osinfo,Options="-h narten",ClientDuration=120]
+
+ # Description:
+ # The above config values sets up the stress tests for the following
+ # stress test clients to be run concurrently:
+ # 1. One ModelWalkStressClient which will use the Name space
+ # "/root/cimv2" and ClassName "CIM_door" overriding any
+ # default value.
+ # This client will be run for 60 minutes then stopped for 10
+ # minutes before it is re-started again. This process will be
+ # repeated for the duration of the stress tests.
+ # 2. Five ModelWalkStressClient's using common values.
+ # 3. Two WrapperStressClients will run the commands
+ # "CLI -l narten niall" concurrently.
+ # 4. Ten WrapperStressCleints will concurrently run the command
+ # "CLI -l narten ei pg_computersystem".
+ # 5. Five WrapperStressCleints will run the command "osinfo -h
+ # narten" concurrently for 120 minutes and then stop.
+ #
+ # Note:
+ # The 17 wrapper clients instances are also connecting to the
+ # same hostname as the other clients.(Please refer to items 3, 4
+ # & 5 under Descriptions)
+ # Please note that the "CLI" command uses -l option while the
+ # "osinfo" command uses -h option to set the hostname respectively.
+
+*******************************************************************************
+3.0 Default Values:
+===============================================================================
+
+ 3.1 Default Hostname will be the local system where the stress tests are
+ run.
+
+ 3.2 Default port will be 5988.
+
+ 3.3 Default "Duration" will be set as 180 minutes.
+
+ 3.4 Default number of instances for each of the known clients is "5".
+
+ 3.5 Default NameSpace when needed will be "root/cimv2".
+
+ 3.6 Default UserName and Password will be blank.
+
+ 3.7 Default will not use SSL.
+
+ 3.8 Default percentage for "ToleranceLevel" will be set as 0%.
+
+ 3.9 Default ClientWait & ClientDuration will be blank.
+
+ 3.10 Default Clients for the stress tests will be set as follows:
+
+ ModelWalkStressClient=5
+ WrapperStressClient=5
+ [ClientName=CLI, Options=niall]
+
+ Note:
+ The above default sets up the stress tests for the following test
+ clients to be run concurrently:
+ Five ModelWalkStressClient instances using default values.
+ Five WrapperStressClient instances running the command "CLI niall".
+
+*****************************************************************************
+4.0 Running a Stress Test using default values:
+=============================================================================
+Assumptions:
+ CIMServer and Stress Test successfully build.
+ $PEGASUS_ROOT, $PEGASUS_HOME and other pegasus environments are
+ appropriately set.
+
+ 4.1 Start the CIM Server on a specific hostname.
+
+ 4.2 Run the following command :
+ (Ensure that the hostname specified below matches where the above
+ CIM Server resides.)
+
+ TestStressTestController -h <hostname>
+
+ NOTE:
+ If the <hostname> is local host run the command without the "-h" option
+ as follows:
+
+ TestStressTestController
+
+ 4.3 The "stressTestController" will search for the default file
+ in the configuration directory.
+
+ 4.4 Assuming that we are using default values but connecting to the
+ specified host, the "stressController" will then invoke the Five
+ ModelWalkStressClient instances using default values & the Five
+ WrapperStressClient instances running the command
+ "CLI niall -l <hostname>" .
+ (See section 3.0 (Default Values) above for reference)
+
+ 4.5 The "TestStressTestController" will log status and other information in its
+ log file.
+
+ 4.6 Each instance of the invoked stressClients(ModelWalkStressClient &
+ Wrapper StressClient) will connect to the specified hostname via the
+ default port and run its operations.
+
+ 4.7 Note that the stress clients will repeat these operations until it
+ unexpectedly ends or is stopped by the "TestStressTestController".
+
+ 4.8 TestStressTestController will monitor the overall status of these stress
+ clients for every One minute interval.
+ - If the overall stress client status is less than or equal to the
+ tolerance level then all is well and all the client instances are
+ allowed to chug along.
+ - if the overall stress client status is greater than the tolerance
+ level, then the stressTestController will terminate all the client
+ instances and subsequently end the stress tests while reporting
+ & loging this failure.
+
+ 4.9 If all is well then the tests will continue till the end of the
+ duration of the stress tests, which for default will be 180 minutes.
+
+*****************************************************************************
+5.0 Running the new "stresstest" target:
+=============================================================================
+
+Assumptions:
+ CIMServer successfully build.
+ $PEGASUS_ROOT, $PEGASUS_HOME and other pegasus environments are
+ appropriately set.
+
+ 5.1 Change directory to $PEGASUS_ROOT
+
+ 5.2 Run the following command.
+ "make stresstests"
+
+ - The new target "stresstests" will run the stress Tests
+ ("stressTestController") using default configuration.
+ The stress test programs are expected to be build already
+ and ready to run.
+
+ - Any failure, will be reported accordingly and end the tests.
+
+ 5.3 Target "tests" can also be run from $PEGASUS_ROOT/test/StressTests/tests
+ These tests will run some usage tests for the "TestStressTestController"
+ Any failure, will be reported accordingly and end the tests.
+ (These tests will be run as part of the nightly test.)
+
+ To invoke this target:
+ - Change directory to $PEGASUS_ROOT/test/StressTests/tests/
+ - Run the following command
+ "make tests"
+
+*****************************************************************************
+6.0 Stress Test Logs:
+=============================================================================
+
+ Stress Test logs will contain general information about the stress tests.
+ Most of the informations concerns configuration properties, client status,
+ controller status, actual tolerance status, started/re-started clients,
+ stopped clients and other general information concerning the tests.
+ A little more detailed logs and status reports are kept when the verbose
+ option is selected.
+
+ 6.1 Log files for the Stress Tests will be saved in the following directory:
+ $PEGASUS_HOME/test/StressTestController/log/
+
+ 6.2 Each test will generate two log files.(One for the controller and one
+ for all the clients executed by this test.)
+
+ 6.3 Log files for the controller can be found in above log directory:
+ and will be named as
+ "<controller_pid>_stressTest_<DDMMYYhhmmss>.log "
+ where,
+ "DD" denotes the day.
+ "MM" denotes the month.
+ "YY" denotes the year.
+ "hh" denotes the hour.
+ "mm" denotes the minutes.
+ "ss" denotes the seconds.
+
+ 6.4 Log file for all the clients intiated by a controller can also be found
+ in the above log directory and will be named as
+ <controller-pid>_StressTestClients.log
+
+ where,
+ "controller-pid" denotes the pid of the TestStressTestController
+
+*******************************************************************************
+7.0 Stress Test Errors:
+===============================================================================
+ There are several sources of errors in the stress test.
+ They are
+
+ 7.1 Stress Test Controller errors
+ (These failures will end the tests)
+ 7.1.1 Invalid command options or operands.
+ 7.1.2 Non-Existing Configuration file.
+ 7.1.3 Syntax Error in Configuration file.
+ 7.1.4 Invalid config property in config file.
+ 7.1.5 Non-Existing Client PID file.(Failed to Communicate with Client)
+ 7.1.6 Error reading Client PID File.
+ 7.1.7 Not within tolerance Error.
+
+ 7.2 Stress Test Client errors
+ 7.2.1 Time out waiting to connect
+ This is an exception thrown by the client. It will be logged and
+ viewed by the controller as a failure.
+
+ 7.2.2 Time out waiting for response
+ This is an exception thrown by the client. It will be logged and
+ viewed by the controller as a failure.
+
+ 7.2.2 Failed getInstance operation for some classes(See Bugs 4957 &
+ 4268).
+
+
+ 7.3 Server Response Errors
+
+ 7.3.1 Varied error response returned by the server.
+ This kind of error will be logged and viewed by the controller as
+ a failure.
+
+*******************************************************************************
+8.0 Other Considerations:
+===============================================================================
+ Compilation of the "Stress Test Clients" and the associated files will be
+ included in the nightly build. However, testing of the "Stress Test
+ Clients" and the associated files will NOT be included in the
+ nightly tests.
diff --git a/test/StressTestController/StressTestController.cpp b/test/StressTestController/StressTestController.cpp
new file mode 100644
index 0000000..195886e
--- /dev/null
+++ b/test/StressTestController/StressTestController.cpp
@@ -0,0 +1,3479 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: John Alex
+//
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Common/Constants.h>
+#include <Pegasus/Common/System.h>
+#include <Pegasus/Common/PegasusVersion.h>
+#include <Pegasus/Common/SSLContext.h>
+#include <Pegasus/getoopt/getoopt.h>
+#include <Pegasus/Common/String.h>
+#include <Pegasus/Client/CIMClient.h>
+#include <Pegasus/Common/FileSystem.h>
+#include <Pegasus/Common/TimeValue.h>
+#include <time.h>
+#include <signal.h>
+#include "StressTestController.h"
+#include "StressTestControllerException.h"
+//
+//Windows
+//
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ // for DWORD etc.
+ #include <windows.h>
+ // getpid() and others
+ typedef DWORD pid_t;
+ #include <process.h>
+#elif !defined(PEGASUS_OS_OS400)
+ #include <unistd.h>
+#endif
+
+//#define DEBUG
+
+#define SIXTYSECONDS 60
+#define MILLISECONDS 1000
+#define CHECKUP_INTERVAL 1
+#define STOP_DELAY 1
+#define SHUTDOWN_DELAY 5
+#define RUN_DELAY 1
+#define DEFAULT_INSTANCE "5"
+
+#define convertmin2millisecs(x) (x * SIXTYSECONDS * MILLISECONDS)
+#define getToleranceInPercent(x,y) (100 - (((y-x)/y) * 100))
+
+
+
+static void endAllTests(int signum);
+
+static void cleanupProcess();
+
+static String convertUint64toString(Uint64 x);
+
+
+PEGASUS_NAMESPACE_BEGIN
+PEGASUS_USING_PEGASUS;
+PEGASUS_USING_STD;
+
+
+
+/**
+ Log file descripter
+*/
+
+/**
+ variable for Signal handler
+*/
+static Boolean Quit = false;
+
+/**
+ The command name.
+ */
+const char StressTestControllerCommand::COMMAND_NAME [] =
+ "TestStressTestController";
+
+
+/**
+ StressTest Configuration file details
+*/
+char StressTestControllerCommand::FILENAME[] = "default_stresstest.conf";
+char StressTestControllerCommand::TESTDIR[] = "/test/";
+char StressTestControllerCommand::STRESSTESTDIR[] = "StressTestController/";
+char StressTestControllerCommand::LOGDIR[] = "log/";
+char StressTestControllerCommand::BINDIR[] = "/bin/";
+char StressTestControllerCommand::DEFAULT_CFGDIR[] =
+ STRESSTEST_DEFAULTCFGDIR;
+char StressTestControllerCommand::DEFAULT_LOGDIR[] =
+ "/test/StressTestController/log/";
+char StressTestControllerCommand::DEFAULT_TMPDIR[] =
+ "/test/StressTestController/tmp/";
+
+String DEFAULT_BINDIR = String::EMPTY;
+
+static Uint32 DEFAULT_CLIENTS = 2;
+static Uint32 Total_Clients = DEFAULT_CLIENTS;
+static Uint32 Total_vClients = DEFAULT_CLIENTS;
+static Uint32 NEW_CLIENTS = 5;
+
+static char MODELWALK_CLIENT[] = "TestModelWalkStressClient";
+static char WRAPPER_CLIENT[] = "TestWrapperStressClient";
+
+/**
+ StressTest Client Status types
+*/
+enum CStatus{
+ VALID_RESPONSE,
+ INVALID_RESPONSE,
+ NO_RESPONSE};
+
+
+/**
+ Temporary arrays to store client information
+*/
+
+/**
+ Client PID's
+*/
+static pid_t *clientPIDs;
+
+/**
+ Client Status
+*/
+static int *clientStatus;
+
+
+/**
+ Client Status
+*/
+static int *prev_clientStatus;
+
+/**
+ Client Instance
+*/
+static int *clientInstance;
+
+/**
+ Indicates if client is Active
+*/
+static Boolean *clientActive;
+
+/**
+ Client status time stamp
+*/
+static Uint64 *clientTimeStamp;
+
+/**
+ Previous client status time stamp
+*/
+static Uint64 *prev_clientTimeStamp;
+
+/**
+ DEFAULT VALUES:
+*/
+
+/**
+ Default duration for the stress tests
+*/
+double StressTestControllerCommand::_duration = 180;
+
+/**
+ Label for the usage string for this command.
+ */
+const char StressTestControllerCommand::_USAGE [] = "Usage: ";
+
+/**
+ The option character used to specify the hostname.
+ */
+const char StressTestControllerCommand::_OPTION_HOSTNAME = 'h';
+
+/**
+ The option character used to specify the port number.
+ */
+const char StressTestControllerCommand::_OPTION_PORTNUMBER = 'p';
+
+/**
+ The option character used to specify SSL usage.
+ */
+const char StressTestControllerCommand::_OPTION_SSL = 's';
+
+/**
+ The option character used to specify the username.
+ */
+const char StressTestControllerCommand::_OPTION_USERNAME = 'u';
+
+/**
+ The option character used to specify the password.
+ */
+const char StressTestControllerCommand::_OPTION_PASSWORD = 'w';
+
+/**
+ The minimum valid portnumber.
+ */
+const Uint32 StressTestControllerCommand::_MIN_PORTNUMBER = 0;
+
+/**
+ The maximum valid portnumber.
+ */
+const Uint32 StressTestControllerCommand::_MAX_PORTNUMBER = 65535;
+
+/**
+ The minimum Duration.
+ */
+const Uint32 StressTestControllerCommand::_MIN_DURATION = 0;
+
+/**
+ The minimum valid Tolerance Level.
+ */
+const Uint32 StressTestControllerCommand::_MIN_TOLERANCE = 0;
+
+/**
+ The maximum valid Tolerance Level.
+ */
+const Uint32 StressTestControllerCommand::_MAX_TOLERANCE = 100;
+
+/**
+ The variable used to specify the hostname.
+ */
+static const char HOSTNAME[] = "hostname";
+
+/**
+ The variable used to specify the port number.
+ */
+static const char PORTNUMBER[] = "port";
+
+/**
+ The variable used to specify SSL usage.
+ */
+static const char SSL [] = "ssl";
+
+/**
+ The variable used to specify the username.
+ */
+static const char USERNAME[] = "username";
+
+/**
+ The variable used to specify the password.
+ */
+static const char PASSWORD[] = "password";
+
+/**
+ The variable used to specify the duration of the tests.
+ */
+static const char DURATION[] = "duration";
+
+/**
+ The variable used to specify the duration of the Client tests.
+ */
+static const char CLIENTDURATION[] = "ClientDuration";
+
+/**
+ The variable used to specify the ToleranceLevel for the tests.
+ */
+static const char TOLERANCELEVEL[] = "TOLERANCELEVEL";
+
+/**
+ The variable used to specify the NameSpace for the tests.
+ */
+static const char NAMESPACE[] = "namespace";
+
+/**
+ The variable used to specify the ClassName for the tests.
+ */
+static const char CLASSNAME[] = "classname";
+
+/**
+ The variable used to specify the Name for the tests.
+ */
+static const char NAME[] = "NAME";
+
+/**
+ The variable used to specify the Clientname for the tests.
+ */
+static const char CLIENTNAME[] = "clientname";
+
+/**
+ The variable used to specify the Clientname for the tests.
+ */
+static const char OPTIONS[] = "options";
+
+/**
+ The variable used to specify the Clientname for the tests.
+ */
+static const char INSTANCE[] = "INSTANCE";
+
+/**
+ The variable used to specify the Clientname for the tests.
+ */
+static const char CLIENTWAIT[] = "CLIENTWAIT";
+
+
+
+/**
+ * Message resource name
+ */
+static const char PASSWORD_PROMPT [] =
+ "Please enter your password: ";
+static const char PASSWORD_BLANK [] =
+ "Password cannot be blank. Please re-enter your password.";
+static const char LONG_HELP[] = "help";
+static const char LONG_VERSION[] = "version";
+static const char LONG_VERBOSE[] = "verbose";
+
+static Boolean IsAClient = false;
+
+static Boolean IsClientOptions = false;
+
+static Boolean IgnoreLine = false;
+
+/**
+
+ Constructs a StressTestControllerCommand and initializes instance variables.
+
+ */
+StressTestControllerCommand::StressTestControllerCommand ()
+{
+
+ _hostName = String ();
+ _hostNameSpecified = false;
+ _portNumber = WBEM_DEFAULT_HTTP_PORT;
+ _portNumberSpecified = false;
+
+ char buffer[32];
+ sprintf(buffer, "%lu", (unsigned long) _portNumber);
+
+ _portNumberStr = buffer;
+
+ _timeout = DEFAULT_TIMEOUT_MILLISECONDS;
+ _userName = String ();
+ _userNameSpecified = false;
+ _password = String ();
+ _passwordSpecified = false;
+ _useSSL = false;
+
+ //
+ // initialize
+ //
+ _clientCount = 0;
+ _currClientCount = 0;
+
+ //
+ // Set up tables for client properties.
+ //
+ _clientTable = new Table[Total_Clients];
+
+ //
+ // Allocate one table to collect all the common properties Thy use AutoPtr
+ //
+ _propertyTable = new Table;
+
+ //
+ // Client Information
+ //
+ _clientCommands = 0;
+ _clientDurations = 0;
+ _clientDelays = 0;
+
+ //
+ // Get environment variables:
+ //
+ pegasusHome = getenv("PEGASUS_HOME");
+
+ DEFAULT_BINDIR = String(pegasusHome);
+ DEFAULT_BINDIR.append(BINDIR);
+
+ _stressTestLogFile = String::EMPTY;
+
+ _stressTestClientPIDFile = String::EMPTY;
+
+ _stressTestClientLogFile = String::EMPTY;
+
+ _tmpStressTestClientPIDFile = String::EMPTY;
+
+
+
+ _usage = String (_USAGE);
+
+ _usage.append (COMMAND_NAME);
+#ifndef DISABLE_SUPPORT_FOR_REMOTE_CONNECTIONS
+ _usage.append (" [ -");
+ _usage.append (_OPTION_SSL);
+ _usage.append (" ] [ -");
+ _usage.append (_OPTION_HOSTNAME);
+ _usage.append (" hostname ] [ -");
+ _usage.append (_OPTION_PORTNUMBER);
+ _usage.append (" portnumber ]\n [ -");
+ _usage.append (_OPTION_USERNAME);
+ _usage.append (" username ] [ -");
+ _usage.append (_OPTION_PASSWORD);
+ _usage.append (" password ]");
+#endif
+ _usage.append (" [ --");
+ _usage.append (LONG_HELP);
+ _usage.append(" ]\n");
+ _usage.append(" ");
+ _usage.append("[ --").append(LONG_VERSION).append(" ]");
+ _usage.append(" [ --").append(LONG_VERBOSE).append(" ]").append(\
+ " [<config_filename>] \n");
+
+ _usage.append("Options : \n");
+ _usage.append(" -h - Connect to CIM Server on specified ");
+ _usage.append("hostname. \n");
+ _usage.append(" --help - Display this help message.\n");
+ _usage.append(" -p - Connect to CIM Server on specified ");
+ _usage.append("portnumber.\n");
+ _usage.append(" -s - Use SSL protocol between Stress Test ");
+ _usage.append("Client\n");
+ _usage.append(" and the CIM Server\n");
+ _usage.append(" -u - Connect to CIM Server using the specified");
+ _usage.append(" username\n");
+ _usage.append(" --version - Display CIM Server version number\n");
+ _usage.append(" --verbose - Display verbose information\n");
+ _usage.append(" -w - Connect to CIM Server using the specified");
+ _usage.append(" password\n");
+ _usage.append("\nOperands : \n");
+ _usage.append(" <config_filename>\n");
+ _usage.append(" - Specifies the name of the configuration ");
+ _usage.append("file that is to be used \n");
+ _usage.append(" for the tests.\n");
+
+ setUsage(_usage);
+
+} /* StressTestControllerCommand */
+
+/**
+
+ Parses the command line, validates the options, and sets instance
+ variables based on the option arguments.
+
+ @param argc the number of command line arguments
+ @param argv the string vector of command line arguments
+
+ @exception CommandFormatException if an error is encountered in parsing
+ the command line
+
+ */
+void StressTestControllerCommand::setCommand (Uint32 argc, char* argv [])
+{
+ Uint32 i = 0;
+ Uint32 c = 0;
+ String GetOptString = String ();
+ getoopt getOpts;
+ _toleranceLevel = 0;
+ _configFilePath = String ();
+ _configFilePathSpecified = false;
+
+ _operationType = OPERATION_TYPE_UNINITIALIZED;
+
+
+ ofstream log_file;
+
+ //
+ // opens the log file
+ //
+ OpenAppend(log_file,_stressTestLogFile);
+
+ if (!log_file)
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Cannot get file "<<_stressTestLogFile<<endl;
+ }
+
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ ":: Preparing to set up parameters: "<<endl;
+
+ //
+ // Construct GetOptString
+ //
+ GetOptString.append (_OPTION_HOSTNAME);
+ GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
+ GetOptString.append (_OPTION_PORTNUMBER);
+ GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
+ GetOptString.append (_OPTION_SSL);
+ GetOptString.append (_OPTION_USERNAME);
+ GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
+ GetOptString.append (_OPTION_PASSWORD);
+ GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
+
+ //
+ // Initialize and parse getOpts
+ //
+ getOpts = getoopt ();
+ getOpts.addFlagspec (GetOptString);
+
+ //
+ // per PEP#167
+ //
+ getOpts.addLongFlagspec(LONG_HELP,getoopt::NOARG);
+ getOpts.addLongFlagspec(LONG_VERSION,getoopt::NOARG);
+ getOpts.addLongFlagspec(LONG_VERBOSE,getoopt::NOARG);
+
+ getOpts.parse (argc, argv);
+
+ if (getOpts.hasErrors ())
+ {
+ log_file.close();
+ CommandFormatException e(getOpts.getErrorStrings () [0]);
+ throw e;
+ }
+
+ //
+ // Get options and arguments from the command line
+ //
+ for (i = getOpts.first(); i < getOpts.last (); i++)
+ {
+ if (getOpts[i].getType() == Optarg::LONGFLAG)
+ {
+ if (getOpts[i].getopt() == LONG_HELP)
+ {
+ _operationType = OPERATION_TYPE_HELP;
+ }
+ else if (getOpts[i].getopt() == LONG_VERSION)
+ {
+ _operationType = OPERATION_TYPE_VERSION;
+ }
+ if (getOpts[i].getopt() == LONG_VERBOSE)
+ {
+ verboseEnabled = true;
+ }
+ }
+ else if (getOpts [i].getType() == Optarg::REGULAR)
+ {
+ //
+ // _configFilePath is the only non-option argument
+ //
+ if (_configFilePathSpecified)
+ {
+ //
+ // more than one _configFilePath argument was found
+ //
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::More than one arguement was found "<<endl;
+ log_file.close();
+ UnexpectedArgumentException e(getOpts[i].Value());
+ throw e;
+ }
+ _configFilePath = getOpts[i].Value();
+ _configFilePathSpecified = true;
+ }
+ else /* getOpts[i].getType() == FLAG */
+ {
+ c = getOpts[i].getopt()[0];
+ switch(c)
+ {
+ case _OPTION_HOSTNAME:
+ {
+ if (getOpts.isSet(_OPTION_HOSTNAME) > 1)
+ {
+ //
+ // More than one hostname option was found
+ //
+ log_file.close();
+ DuplicateOptionException e(_OPTION_HOSTNAME);
+ throw e;
+ }
+ _hostName = getOpts [i].Value ();
+ _hostNameSpecified = true;
+ if (!_propertyTable->insert("hostname", _hostName))
+ {
+ // shouldn't get here
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<<"::Property Name name already saved: "<<
+ "hostname"<<endl;
+ }
+ }
+ break;
+ }
+ case _OPTION_PORTNUMBER:
+ {
+ if (getOpts.isSet(_OPTION_PORTNUMBER) > 1)
+ {
+ //
+ // More than one portNumber option was found
+ //
+ log_file.close();
+ DuplicateOptionException e(_OPTION_PORTNUMBER);
+ throw e;
+ }
+ _portNumberStr = getOpts [i].Value ();
+ try
+ {
+ getOpts[i].Value(_portNumber);
+ }
+ catch (const TypeMismatchException&)
+ {
+ log_file.close();
+ InvalidOptionArgumentException e(
+ _portNumberStr,
+ _OPTION_PORTNUMBER);
+ throw e;
+ }
+ _portNumberSpecified = true;
+ if (!_propertyTable->insert("port", _portNumberStr))
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<<"::Property Name:duplicate name already saved:"
+ <<"port"<<endl;
+ }
+ }
+ break;
+ }
+ case _OPTION_SSL:
+ {
+ //
+ // Use port 5989 as the default port for SSL
+ //
+ _useSSL = true;
+ if (!_portNumberSpecified)
+ {
+ _portNumber = 5989;
+ _portNumberStr = "5989";
+ if (!_propertyTable->insert("port", _portNumberStr))
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<<"::Property Name already saved: "<<"port"<<
+ endl;
+ }
+ }
+ }
+ if (!_propertyTable->insert("ssl", ""))
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<<"::Property Name already saved: "<<"ssl"<<
+ endl;
+ }
+ }
+ break;
+ }
+ case _OPTION_USERNAME:
+ {
+ if (getOpts.isSet(_OPTION_USERNAME) > 1)
+ {
+ //
+ // More than one username option was found
+ //
+ log_file.close();
+ DuplicateOptionException e(_OPTION_USERNAME);
+ throw e;
+ }
+ _userName = getOpts[i].Value();
+ _userNameSpecified = true;
+ if (!_propertyTable->insert("username", _userName))
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<< "::Property Name already saved: "<<
+ "username"<<endl;
+ }
+ }
+ break;
+ }
+ case _OPTION_PASSWORD:
+ {
+ if (getOpts.isSet(_OPTION_PASSWORD) > 1)
+ {
+ //
+ // More than one password option was found
+ //
+ log_file.close();
+ DuplicateOptionException e(_OPTION_PASSWORD);
+ throw e;
+ }
+ _password = getOpts[i].Value();
+ _passwordSpecified = true;
+ if (!_propertyTable->insert("password", _password))
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<<"::Property Name already saved: "<<
+ "password"<<endl;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ //
+ // This path should not be hit
+ // PEP#167 unless an empty '-' is specified
+ //
+ log_file.close();
+ String ErrReport =
+ String(StressTestControllerCommand::COMMAND_NAME);
+ ErrReport.append("::Invalid or unknown option specified");
+ throw StressTestControllerException(ErrReport);
+
+ break;
+ }
+ }
+ }
+ }
+ //
+ // More validation:
+ // No portNumber specified
+ // Default to WBEM_DEFAULT_PORT
+ // Already done in constructor
+ //
+ if (getOpts.isSet(_OPTION_PORTNUMBER) == 1)
+ {
+ if (_portNumber > _MAX_PORTNUMBER)
+ {
+ //
+ // Portnumber out of valid range
+ //
+ log_file.close();
+ InvalidOptionArgumentException e(_portNumberStr,
+ _OPTION_PORTNUMBER);
+ throw e;
+ }
+ }
+ log_file.close();
+} /* setCommand */
+
+/**
+
+ Generates commands and its options for each of the clients.
+ The client table is traversed to generate each of the client commands.
+ The Commands, Duration and Delays for each client are saved in
+ the following array's respectively:
+ _clientCommands
+ _clientDurations
+ _clientDelays
+
+ @param log_file The log file.
+
+ @return 0 if the command is successfully generated
+ 1 if the command cannot be generated.
+ */
+Boolean StressTestControllerCommand::generateClientCommands(ostream& log_file)
+{
+
+ String client_command = String::EMPTY;
+ double duration = _duration;
+ double delay = 0;
+
+ //
+ // Array's to store client specific information
+ //
+ _clientCommands = new String[_clientCount];
+ _clientDurations = new Uint64[_clientCount];
+ _clientDelays = new Uint64[_clientCount];
+
+ //
+ // Retrieve all the client options from the client table
+ // and build commands for respective clients.
+ // Add appropriate options to command string as required
+ //
+ for (Uint32 j=0; j< _clientCount; j++)
+ {
+ delay = 0;
+ String clientName = String::EMPTY;
+ String clientInst = String::EMPTY;
+ //
+ // Stress Client Name must exist for each client/client table
+ //
+ if (!_clientTable[j].lookup(NAME, clientName))
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Required property NAME not found."<<endl;
+ return false;
+ }
+ //
+ // Start the command string with the client name.
+ //
+ client_command = clientName;
+
+ //
+ // Generate the commands for each client from each client table.
+ //
+ for (Table::Iterator i = _clientTable[j].start(); i; i++)
+ {
+ if (String::equalNoCase(i.key(),HOSTNAME))
+ {
+ client_command.append(" -hostname ");
+ if (_hostNameSpecified)
+ {
+ client_command.append(_hostName);
+ }
+ else
+ {
+ client_command.append(i.value());
+ }
+ }
+ else if (String::equalNoCase(i.key(),NAME))
+ {
+ //
+ // should be ignored - already saved using clientName
+ //
+ }
+ else if (String::equalNoCase(i.key(),PORTNUMBER))
+ {
+ client_command.append(" -");
+ client_command.append(PORTNUMBER);
+ client_command.append(" ");
+ if (_portNumberSpecified)
+ {
+ client_command.append(_portNumberStr);
+ }
+ else
+ {
+ client_command.append(i.value());
+ }
+ }
+ else if (String::equalNoCase(i.key(),SSL))
+ {
+ client_command.append(" -");
+ client_command.append(SSL);
+ }
+ else if (String::equalNoCase(i.key(),USERNAME))
+ {
+ client_command.append(" -");
+ client_command.append(USERNAME);
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ else if (String::equalNoCase(i.key(),PASSWORD))
+ {
+ client_command.append(" -");
+ client_command.append(PASSWORD);
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ else if (String::equalNoCase(i.key(),CLIENTNAME))
+ {
+ client_command.append(" -");
+ client_command.append(CLIENTNAME);
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ else if (String::equalNoCase(i.key(),OPTIONS))
+ {
+ client_command.append(" -");
+ client_command.append(OPTIONS);
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ else if (String::equalNoCase(i.key(),NAMESPACE))
+ {
+ client_command.append(" -");
+ client_command.append(NAMESPACE);
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ else if (String::equalNoCase(i.key(),CLASSNAME))
+ {
+ client_command.append(" -");
+ client_command.append(CLASSNAME);
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ else if ((String::equalNoCase(i.key(),INSTANCE))
+ ||(String::equalNoCase(i.key(),CLIENTWAIT))
+ ||(String::equalNoCase(i.key(),CLIENTDURATION)))
+ {
+ //
+ // do nothing here
+ // will be utilized to run the clients later.
+ //
+ }
+ else
+ {
+ //
+ // Save all other options for the commands
+ //
+ client_command.append(" -");
+ client_command.append(i.key());
+ client_command.append(" ");
+ client_command.append(i.value());
+ }
+ }
+ //
+ // Include verbose if enabled to clients
+ //
+ if (verboseEnabled)
+ {
+ client_command.append(" -verbose ");
+ }
+
+ //
+ // Acquire all the common properties listed in the property table
+ // from config file and include it as part of the client command
+ // as required.
+ //
+ for (Table::Iterator k = _propertyTable->start(); k; k++)
+ {
+ String propertyValue = String::EMPTY;
+ //
+ // Only include the common properties that are not already
+ // listed for the clients.
+ //
+ if (!_clientTable[j].lookup(k.key(), propertyValue))
+ {
+ //
+ // Include options other than ToleranceLevel
+ // clientDuration,clientwait and Duration
+ // in the command string for the clients.
+ //
+ if ((!String::equalNoCase(k.key(),TOLERANCELEVEL))
+ && (!String::equalNoCase(k.key(),CLIENTDURATION))
+ && (!String::equalNoCase(k.key(),CLIENTWAIT))
+ && (!String::equalNoCase(k.key(),DURATION)))
+ {
+ client_command.append(" -");
+ client_command.append(k.key());
+ //
+ // No values required for SSL
+ //
+ if (!String::equalNoCase(k.key(),SSL))
+ {
+ client_command.append(" ");
+ client_command.append(k.value());
+ }
+ }
+ }
+ //
+ // Use default duration if one was not specified in the Config file.
+ //
+ if (String::equalNoCase(k.key(),DURATION))
+ {
+ duration = atof(k.value().getCString());
+ }
+ else
+ {
+ duration = _duration;
+ }
+ } /* for (Table::Iterator k = _propertyTable->start(); k; k++) */
+
+ //
+ // Looking up table while ignoring cases for Client Duration/Wait.
+ //
+ for (Table::Iterator k = _clientTable[j].start(); k; k++)
+ {
+ //
+ // Overwrite duration if client duration set
+ //
+ if (String::equalNoCase(k.key(),CLIENTDURATION))
+ {
+ duration = atof(k.value().getCString());
+ }
+ if (String::equalNoCase(k.key(),CLIENTWAIT))
+ {
+ delay = atof(k.value().getCString());
+ }
+ }
+
+ //
+ // Save the generated command to corresponding element in the
+ // clientCommand array.
+ //
+ _clientCommands[j] = client_command;
+
+ //
+ // Converting minutes to milliseconds
+ //
+ _clientDurations[j] = (Uint64)convertmin2millisecs(duration);
+ _clientDelays[j] = (Uint64)convertmin2millisecs(delay);
+
+ //
+ // Saving logs
+ //
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Client Command[";
+ log_file<<j<<"]"<<endl;
+ log_file<<" "<<_clientCommands[j]<<endl;
+ log_file<<" Client Duration: "<<
+ convertUint64toString(_clientDurations[j])<<endl;
+ log_file<<
+ " Client Delay: "<<convertUint64toString(_clientDelays[j])<<endl;
+
+ //
+ // Verbose
+ //
+ if (verboseEnabled)
+ {
+ cout<<
+ StressTestControllerCommand::COMMAND_NAME<<"::Client Command[";
+ cout<<j<<"]"<<endl;
+ cout<<" "<<_clientCommands[j]<<endl;
+ cout<<" Client Duration: "<<
+ convertUint64toString(_clientDurations[j])<<endl;
+ cout<<" Client Delay: "<<convertUint64toString(_clientDelays[j])<<
+ endl;
+ }
+ } /* for(Uint32 j=0; j< _clientCount; j++) */
+ return true;
+} /* generateClientCommands */
+
+/*
+ Executes the command and writes the results to the PrintWriters.
+ This method is where the clients are intiated.
+ The clients are kept running until its duration is met
+ or the controller is interrupted by a SIGINT or SIGABRT signal
+ or if the controller failed to acquire the clientPIDs when needed.
+
+ Clients with clientWait, will be stopped when its duration is met and
+ then restarted after its wait period is completed. This will continue
+ until the end of the overall duration.
+ When the overall duration has ended or the controller is interupted then
+ the controller will read the PID file to update its clients PID and
+ request all the clients to end its processes.
+
+ @param outPrintWriter the ostream to which output should be
+ written
+ @param errPrintWriter the ostream to which error output should be
+ written
+
+ @return 0 if the command is successful
+ 1 if an error occurs in executing the command
+
+ */
+Uint32 StressTestControllerCommand::execute (
+ ostream& outPrintWriter,
+ ostream& errPrintWriter)
+{
+
+ int actual_client = 0;
+ Uint64 startMilliseconds = 0;
+ Uint64 nowMilliseconds = 0;
+ Uint64 stopMilliseconds = 0;
+ Uint64 timeoutMilliseconds = 0;
+ Uint64 *clientStartMilliseconds = 0;
+ Uint64 *clientStopMilliseconds = 0;
+ Uint64 *clientDelayMilliseconds = 0;
+ Boolean *clientStopped = 0;
+ Boolean *clientDelayed = 0;
+ String act_command = String::EMPTY;
+ Boolean TestFailed = false;
+ char str[15];
+ char strTime[256];
+ struct tm tmTime;
+
+
+
+ //
+ // log file
+ //
+ ofstream log_file;
+
+ //
+ // open the file
+ //
+ OpenAppend(log_file,_stressTestLogFile);
+
+ //
+ // Failed to read log file.
+ //
+ if (!log_file)
+ {
+ log_file.close();
+ if (verboseEnabled)
+ {
+ outPrintWriter<<StressTestControllerCommand::COMMAND_NAME;
+ outPrintWriter<<"Cannot read file "<<_stressTestLogFile<<endl;
+ }
+ return RC_ERROR;
+ }
+
+ //
+ // Display usage message if help was specified
+ //
+ if ( _operationType == OPERATION_TYPE_HELP )
+ {
+ outPrintWriter << _usage << endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Listing usage information "<<endl;
+ log_file.close();
+ //
+ // No need for the client pid and log file.
+ //
+ FileSystem::removeFile(_stressTestClientPIDFile);
+ FileSystem::removeFile(_stressTestClientLogFile);
+ return (RC_SUCCESS);
+ }
+ //
+ // Display PEGASUS version if version was specified
+ //
+ else if ( _operationType == OPERATION_TYPE_VERSION )
+ {
+ outPrintWriter << "Version " << PEGASUS_PRODUCT_VERSION << endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Listing version information "<<endl;
+ log_file<<"Version " << PEGASUS_PRODUCT_VERSION << endl;
+ log_file.close();
+ //
+ // No need for the client pid and log file.
+ //
+ FileSystem::removeFile(_stressTestClientPIDFile);
+ FileSystem::removeFile(_stressTestClientLogFile);
+ return (RC_SUCCESS);
+ }
+
+ //
+ // gracefully shutdown when interrupted
+ //
+ signal(SIGABRT, endAllTests);
+ signal(SIGINT, endAllTests);
+
+ //
+ // Allocate variables necessary to run clients.
+ //
+ if(_clientCount > 0)
+ {
+ clientInstance = new int[_clientCount];
+ clientStartMilliseconds = new Uint64[_clientCount];
+ clientStopMilliseconds = new Uint64[_clientCount];
+ clientDelayMilliseconds = new Uint64[_clientCount];
+ clientStopped = new Boolean[_clientCount];
+ clientDelayed = new Boolean[_clientCount];
+ }
+ else
+ {
+ errPrintWriter << "Stress Tests must have at least one Client." << endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Stress Tests must have at least one Client."<<endl;
+ log_file.close();
+ return (RC_ERROR);
+ }
+
+ try
+ {
+ //
+ // Initializing the Boolean array's to false.
+ //
+ for (Uint32 i=0;i<_clientCount;i++)
+ {
+ clientStopped[i] = false;
+ clientDelayed[i] = false;
+ }
+ //
+ // Set up duration of the tests
+ //
+ startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+ nowMilliseconds = startMilliseconds;
+ timeoutMilliseconds = (Uint64)convertmin2millisecs(_duration);
+ stopMilliseconds = nowMilliseconds + timeoutMilliseconds;
+
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ ":: Test Duration information "<<endl;
+ log_file<<" Start Time in milliseconds: "<<
+ convertUint64toString(startMilliseconds)<<endl;
+ log_file<<" Total duration in milliseconds: "<<
+ convertUint64toString(timeoutMilliseconds)<<endl;
+ log_file<<" Actual Stop Time in milliseconds: "<<
+ convertUint64toString(stopMilliseconds)<<endl;
+ //
+ // Verbose details for Stress Test duration
+ //
+ if (verboseEnabled)
+ {
+ outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
+ ":: Test Duration information "<<endl;
+ outPrintWriter<<" Start Time in milliseconds: "<<
+ convertUint64toString(startMilliseconds)<<endl;
+ outPrintWriter<<" Total duration in milliseconds: "<<
+ convertUint64toString(timeoutMilliseconds)<<endl;
+ outPrintWriter<<
+ " Actual Stop Time in milliseconds: "<<
+ convertUint64toString(stopMilliseconds)<<endl;
+ }
+
+ //
+ // First Tolerance check up interval is set up to be twice
+ // the CHECKUP_INTERVAL. This should give the clients enough time
+ // to update its PID, status etc.
+ //
+ Uint64 nextCheckupInMillisecs =
+ (Uint64)convertmin2millisecs(2 * CHECKUP_INTERVAL) + nowMilliseconds;
+ //
+ // Main "while" loop where the clients are initiated.
+ //
+ while(stopMilliseconds > nowMilliseconds)
+ {
+
+ //
+ // Small delay in the while loop seemed to reduce the CPU usage
+ // considerably in Windows. (From 80% to 1%)
+ //
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ sleep(RUN_DELAY);
+#else
+ Sleep(RUN_DELAY * 1000);
+#endif
+
+ //
+ // Quit if SIGINT, SIGABRT is caught
+ // So the clients can be gracefully shutdown.
+ //
+ if(Quit)
+ {
+ log_file<<
+ "Test interrupted by either SIGINT or SIGABORT."<<endl;
+ TestFailed = true;
+ break;
+ }
+ //
+ // The following block will be where clients are executed initially.
+ //
+ if(!actual_client)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Running the following tests: "<<endl;
+ outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Running the following tests: "<<endl;
+ for (Uint32 j=0; j< _clientCount; j++)
+ {
+ String clientInst = String::EMPTY;
+ //
+ // Acquire the client Instance for each clients
+ //
+ if (!_clientTable[j].lookup(INSTANCE, clientInst))
+ {
+ String ErrReport = String("Invalid Property Value: ");
+ ErrReport.append(INSTANCE);
+ ErrReport.append("=");
+ ErrReport.append(clientInst);
+ throw StressTestControllerException(ErrReport);
+ }
+ clientInstance[j] = atoi(clientInst.getCString());
+
+ //
+ // Acquire and set client specific duration
+ //
+ clientStartMilliseconds[j] =
+ TimeValue::getCurrentTime().toMilliseconds();
+ clientStopMilliseconds[j] =
+ clientStartMilliseconds[j] + _clientDurations[j];
+
+ //
+ // for verbose only
+ //
+ if (verboseEnabled)
+ {
+ outPrintWriter<<"Client:"<<"["<<j<<"]"<<endl;
+ log_file<<"Client:"<<"["<<j<<"]"<<endl;
+ outPrintWriter<<"ClientStart:"<<
+ convertUint64toString(clientStartMilliseconds[j])<<
+ endl;
+ outPrintWriter<<"ClientStop:"<<
+ convertUint64toString(clientStopMilliseconds[j])<<
+ endl;
+ outPrintWriter<<"ClientDuration:"<<
+ convertUint64toString(_clientDurations[j])<<endl;
+ log_file<<"ClientStart:"<<
+ convertUint64toString(clientStartMilliseconds[j])<<
+ endl;
+ log_file<<"ClientStop:"<<
+ convertUint64toString(clientStopMilliseconds[j])<<
+ endl;
+ log_file<<
+ "ClientDuration:"<<
+ convertUint64toString(_clientDurations[j])<<endl;
+ }
+ log_file<<
+ "Number of instances of this client: "<<
+ clientInstance[j]<<endl;
+ if(verboseEnabled)
+ {
+ outPrintWriter<<
+ "Number of instances of this client:"<<
+ clientInstance[j]<<endl;
+ }
+ //
+ // Execute each instance of the client.
+ // - Additional required parameters are added to the
+ // commands.
+ // like, -clientid, -pidfile, -clientlog
+ //
+ for (int instanceID =0;instanceID<clientInstance[j];
+ instanceID++)
+ {
+ outPrintWriter<<
+ "Running Client("<<actual_client<<")"<<endl;
+ log_file<<
+ "Running Client("<<actual_client<<")"<<endl;
+ act_command=String::EMPTY;
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ act_command.append("start ");
+#endif
+ //
+ // Adding all the required parameters for the command.
+ //
+ act_command.append(_clientCommands[j].getCString());
+ act_command.append(" -clientid ");
+ sprintf(str,"%d",actual_client);
+ act_command.append(str);
+ act_command.append(" -pidfile ");
+ act_command.append(" \"");
+ act_command.append(_stressTestClientPIDFile);
+ act_command.append("\"");
+ act_command.append(" -clientlog");
+ act_command.append(" \"");
+ act_command.append(_stressTestClientLogFile);
+ act_command.append("\"");
+ act_command.append("&");
+ if (verboseEnabled)
+ {
+ outPrintWriter<<" "<<act_command<<endl;
+ tmTime = getCurrentActualTime();
+ strftime(
+ strTime,
+ 256,
+ "%d/%m/%Y at %H:%M:%S\n",
+ &tmTime);
+ log_file<<
+ StressTestControllerCommand::COMMAND_NAME<<
+ "::Running following command on "<<
+ strTime<<endl;
+ log_file<<" ("<<actual_client<<") \n"<<
+ act_command<<endl;
+ }
+
+ //
+ // Executing the Client
+ //
+ int rc = system(act_command.getCString());
+ //
+ // Continue even if the client failed to Execute
+ // This failure is validated with Tolerance level later
+ //
+ if (rc)
+ {
+ log_file<<"Command failed to Execute."<<endl;
+ if (verboseEnabled)
+ {
+ outPrintWriter<<
+ "Command failed to Execute."<<endl;
+ }
+ }
+ //
+ // Increment the actual number of clients
+ //
+ ++actual_client;
+ } /* for(int instanceID =0;instanceID<clientInstance[j]...*/
+
+ }/* for(Uint32 j=0; j< _clientCount; j++) */
+
+ //
+ //retrieve all PIDs and status;
+ //
+ clientPIDs = new pid_t[actual_client];
+ clientStatus = new int[actual_client];
+ prev_clientStatus = new int[actual_client];
+ clientTimeStamp = new Uint64[actual_client];
+ prev_clientTimeStamp = new Uint64[actual_client];
+ clientActive = new Boolean[actual_client];
+ nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+ for (int i=0;i<actual_client;i++)
+ {
+ clientPIDs[i] = 9999999;
+ clientStatus[i] = NO_RESPONSE;
+ clientActive[i] = true;
+ clientTimeStamp[i] = nowMilliseconds;
+ prev_clientTimeStamp[i] = nowMilliseconds;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Getting client PID's and status. "<<endl;
+ if (verboseEnabled)
+ {
+ outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Getting client PID's and status. "<<endl;
+ }
+ int rc = _getClientPIDs(actual_client,log_file);
+ if (!rc)
+ {
+ outPrintWriter<<
+ "Failed to communicate with clients."<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Failed to communicate with clients. "<<endl;
+ log_file<<
+ " ::Failed to get client PID & status. "
+ <<endl;
+ TestFailed = true;
+ break;
+ }
+ }/* if (!actual_client) */
+ else
+ {
+ /**
+ Every CHECKUP_INTERVAL minutes check to see if tests are
+ within tolerance. Tests will cease to run if they
+ are not within tolerance. The controller will stop
+ all the clients and then exit.
+ */
+
+ //
+ // Retreive all the client PIDs
+ //
+ int rc = _getClientPIDs(actual_client,log_file);
+
+ //
+ // Get Current Time
+ //
+ nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+
+ //
+ // Check tolerance level if its time
+ //
+ if (nowMilliseconds >= nextCheckupInMillisecs)
+ {
+ //
+ // Set up the next tolerance time
+ //
+ nextCheckupInMillisecs =
+ (Uint64)convertmin2millisecs(CHECKUP_INTERVAL) +
+ nowMilliseconds;
+ //
+ // End tests when failed to acquire the Client PID or
+ // status.
+ //
+ if (!rc)
+ {
+ outPrintWriter<<
+ "Failed to communicate with clients."<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Failed to communicate with clients. "<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Get Client PID FAILED. "<<endl;
+ TestFailed = true;
+ break;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Checking current tolerance level. "<<endl;
+ //
+ // Output Client info if verbose is enabled.
+ //
+ if (verboseEnabled)
+ {
+ outPrintWriter<<
+ StressTestControllerCommand::COMMAND_NAME<<
+ "::Checking current tolerance level. "<<endl;
+ for (int i=0;i< actual_client; i++)
+ {
+ outPrintWriter <<" Client: "<<i;
+ outPrintWriter <<" PID: "<<clientPIDs[i]<<", ";
+ outPrintWriter <<" Status: "<<clientStatus[i]<<endl;
+ log_file <<" Client: "<<i;
+ log_file <<" PID: "<<clientPIDs[i]<<", ";
+ log_file <<" Status: "<<clientStatus[i]<<", ";
+ log_file<<" TimeStamp: "<<
+ convertUint64toString(clientTimeStamp[i])<<
+ endl;
+ }
+ }
+ //
+ // Check the actual tolerance level
+ //
+ Boolean withinTolerance = _checkToleranceLevel(
+ actual_client,
+ nowMilliseconds,
+ log_file);
+ //
+ // End tests if not within tolerance
+ //
+ if (!withinTolerance)
+ {
+ log_file<<"FAILED::Tests NOT within tolerance."<<endl;
+ errPrintWriter<<"FAILED::Tests NOT within tolerance."
+ <<endl;
+ TestFailed = true;
+ break;
+ }
+ //
+ // Within Tolerance - Continue tests.
+ //
+ log_file<<"********Tests are within tolerance.********* "<<
+ endl;
+ if (verboseEnabled)
+ {
+ outPrintWriter<<
+ " ********Tests are within tolerance.**********"<<
+ endl;
+ }
+ } /* if (nowMilliseconds >= nextCheckupInMillisecs)*/
+ //
+ // Stop clients with delay
+ //
+ for (Uint32 clientID=0; clientID < _clientCount; clientID++)
+ {
+ //
+ // Get Current time
+ //
+ nowMilliseconds =
+ TimeValue::getCurrentTime().toMilliseconds();
+
+ //
+ // Stop only running clients as required.
+ //
+ if (!clientStopped[clientID])
+ {
+ //
+ // If Client's duration is up
+ //
+ if (clientStopMilliseconds[clientID]<= nowMilliseconds)
+ {
+ //
+ // Stop all the instances of this client
+ //
+ for (int instanceID =0;
+ instanceID<clientInstance[clientID];
+ instanceID++)
+ {
+ log_file<<"Stopping client:("<<
+ clientID+instanceID<<")"<<endl;
+ log_file<<" with PID = "<<
+ clientPIDs[clientID+instanceID]<<endl;
+ outPrintWriter<<"Stopping client:("<<
+ clientID+instanceID<<")"<<endl;
+ outPrintWriter<<" with PID = "<<
+ clientPIDs[clientID+instanceID]<<endl;
+ if (verboseEnabled)
+ {
+ tmTime = getCurrentActualTime();
+ strftime(
+ strTime,
+ 256,
+ "%d/%m/%Y at %H:%M:%S\n",
+ &tmTime);
+ log_file<<" Stopped on "<<strTime<<endl;
+ }
+ String stopClientFile = String::EMPTY;
+ stopClientFile.append(pegasusHome);
+ stopClientFile.append(DEFAULT_TMPDIR);
+ stopClientFile.append("STOP_");
+ sprintf(
+ str,
+ "%d",
+ clientPIDs[clientID+instanceID]);
+ stopClientFile.append(str);
+ //
+ // Required for Windows
+ //
+ ofstream stop_file(
+ stopClientFile.getCString(),
+ ios::out);
+ stop_file << "Stop Client PID : "<<
+ clientPIDs[clientID + instanceID]<<
+ endl;
+ stop_file.close();
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ // one more way to stop the clients.
+ int rc =
+ kill(clientPIDs[clientID+instanceID], SIGINT);
+ if (rc)
+ {
+ outPrintWriter<<"FAILED to stop client:("<<
+ clientID+instanceID<<")"<<endl;
+ log_file<<"FAILED to stop client:("<<
+ clientID + instanceID<<")"<<endl;
+ }
+#endif
+ //
+ // Set the client as inactive.
+ //
+ clientActive[clientID + instanceID] = false;
+ }/* for (int instanceID =0;instanceID<clientInst..*/
+ //
+ // indicate that the client was stopped.
+ //
+ clientStopped[clientID] = true;
+ //
+ // If the Client has a Wait time
+ //
+ if (_clientDelays[clientID] !=0)
+ {
+ clientDelayMilliseconds[clientID] =
+ nowMilliseconds + _clientDelays[clientID];
+ clientDelayed[clientID] = true;
+ }
+ } /* if (clientStopMilliseconds[clientID]<= nowMilli..*/
+ } /* if (!clientStopped[clientID]) */
+ else
+ {
+ //
+ // Only restart clients that are waiting.
+ //
+ if (clientDelayed[clientID])
+ {
+ //
+ // When waiting period is consumed.
+ //
+ if (clientDelayMilliseconds[clientID]<=
+ nowMilliseconds)
+ {
+ //
+ // Restart all the instances of the client.
+ //
+ for (int instanceID =0;
+ instanceID<clientInstance[clientID];
+ instanceID++)
+ {
+ act_command=String::EMPTY;
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ act_command.append("start ");
+#endif
+ act_command.append(
+ _clientCommands[clientID].getCString());
+ act_command.append(" -clientid ");
+ sprintf(str,"%d",clientID+instanceID);
+ act_command.append(str);
+ act_command.append(" -pidfile ");
+ act_command.append(" \"");
+ act_command.append(_stressTestClientPIDFile);
+ act_command.append("\"");
+ act_command.append(" -clientlog");
+ act_command.append(" \"");
+ act_command.append(_stressTestClientLogFile);
+ act_command.append("\"");
+ act_command.append("&");
+ log_file<<"Restarting client:("<<
+ clientID+instanceID<<")"<<endl;
+ outPrintWriter<<"Restarting client:("<<
+ clientID+instanceID<<")"<<endl;
+ if (verboseEnabled)
+ {
+ outPrintWriter<<" "<<act_command<<endl;
+ log_file<<" ("<<
+ clientID+instanceID<<
+ ") \n"<<act_command<<endl;
+ tmTime = getCurrentActualTime();
+ strftime(
+ strTime,
+ 256,
+ "%d/%m/%Y at %H:%M:%S\n",
+ &tmTime);
+ log_file<<" Restarted on "<<
+ strTime<<endl;
+ }
+ int rc = system(act_command.getCString());
+ if (rc)
+ {
+ log_file<<"Command failed to Execute."<<
+ endl;
+ if (verboseEnabled)
+ {
+ outPrintWriter<<act_command<<
+ "Command failed to Execute."<<
+ endl;
+ }
+ }
+ clientActive[clientID+instanceID] = true;
+ } /* for (int instanceID =0;instanceID .. */
+ clientStopMilliseconds[clientID] =
+ nowMilliseconds +
+ _clientDurations[clientID];
+ clientStopped[clientID] = false;
+ clientDelayed[clientID] = false;
+ }/* if(clientDelayMilliseconds[clientID]<=nowMi.. */
+ } /* if(clientDelayed[clientID]) */
+ } /* else ..*/
+ } /* for(Uint32 clientID=0;clientID < _clientCount;clientID++)*/
+ } /* else for if(!actual_client) */
+ //
+ // Get Current time
+ //
+ nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
+
+ } /* while(stopMilliseconds > nowMilliseconds) */
+
+ }//try
+
+ catch (const StressTestControllerException& e)
+ {
+ errPrintWriter << StressTestControllerCommand::COMMAND_NAME <<
+ ": " << e.getMessage () << endl;
+ return (RC_ERROR);
+ }
+
+ //
+ // Stress Tests should be stopped.
+ //
+ outPrintWriter<<"Ending tests::Preparing to stop all the clients."<<endl;
+ log_file<<"Ending tests::Preparing to stop all the clients."<<endl;
+
+ // Waiting to allow any clients that might have been re-started
+ // just before the tests were ended to add
+ // its pid to the pid file.
+
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ sleep(STOP_DELAY);
+#else
+ Sleep(STOP_DELAY * 1000);
+#endif
+
+ //
+ // get all the clientPIDs before it is stopped.
+ //
+ int rc = _getClientPIDs(actual_client,log_file);
+ if (!rc)
+ {
+ outPrintWriter<<"Failed to communicate with clients."<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Failed to communicate with clients. "<<endl;
+ log_file<<" ::Failed to get client PID & status. "<<
+ endl;
+ TestFailed = true;
+ }
+ tmTime = getCurrentActualTime();
+ strftime(strTime,256,"%d/%m/%Y at %H:%M:%S\n",&tmTime);
+ log_file<<"Ending tests:: Stopping all the clients on "<<strTime <<endl;
+ for (int i=0;i<actual_client;i++)
+ {
+ if(verboseEnabled)
+ {
+ outPrintWriter<<"Stopping Client("<<i<<") with PID:"<<
+ clientPIDs[i]<<endl;
+ }
+ log_file<<"Stopping Client("<<i<<") with PID:"<<clientPIDs[i]<<endl;
+ //
+ // Required for Windows
+ //
+ String stopClientFile = String::EMPTY;
+ stopClientFile.append(pegasusHome);
+ stopClientFile.append(DEFAULT_TMPDIR);
+ stopClientFile.append("STOP_");
+ sprintf(str,"%d",clientPIDs[i]);
+ stopClientFile.append(str);
+ ofstream stop_file(stopClientFile.getCString(),ios::out);
+ stop_file << "Stop Client PID : "<<clientPIDs[i]<<endl;
+ stop_file.close();
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ // Another way to stop the client
+ int rc = 0;
+ rc = kill(clientPIDs[i], SIGINT);
+ if (rc)
+ {
+ if (verboseEnabled)
+ {
+ outPrintWriter<<"Failed to stop client:("<<i<<")"<<endl;
+ }
+ log_file<<"Failed to stop client:("<<i<<")"<<endl;
+ }
+#endif
+ }
+ if (verboseEnabled)
+ {
+ outPrintWriter<<"Cleaning all resources"<<endl;
+ }
+ log_file<<"Cleaning all resources."<<endl;
+ cleanupProcess();
+
+ //
+ // Waiting to allow clients to shutdown
+ //
+#ifndef PEGASUS_OS_TYPE_WINDOWS
+ sleep(SHUTDOWN_DELAY);
+#else
+ Sleep(SHUTDOWN_DELAY * 1000);
+#endif
+ //
+ // If the test did not run to completition
+ //
+ if (TestFailed)
+ return(RC_ERROR);
+
+ return (RC_SUCCESS);
+} /* execute */
+
+
+/*
+ Retrieves the contents of the config file if specified or uses default
+ values from either the default config file
+
+ @param fileName The specified or default config file for the
+ tests.
+ @param log_file The log file.
+
+ @return true if the file was read successfully
+ false if file was not read successfully.
+
+ */
+Boolean StressTestControllerCommand::getFileContent(
+ String fileName,
+ ostream& log_file)
+{
+ String configData = String::EMPTY;
+ String line;
+ int lineNumber = 0;
+ Boolean isSuccess = true;
+ String name = String::EMPTY;
+ String value = String::EMPTY;
+ String ErrReports = String::EMPTY;
+
+ ifstream ifs;
+
+ //
+ // Open the config file and read the stress test configuration data
+ //
+ Open(ifs,fileName);
+ if (!ifs)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Cannot read config file: "<<fileName<<endl;
+ throw NoSuchFile(fileName);
+ }
+
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Storing client details. "<<endl;
+ if (verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Storing config details. "<<endl;
+ }
+ //
+ // Get each line of the file.
+ //
+ while (GetLine(ifs, line))
+ {
+ ++lineNumber;
+ IsAClient = false;
+ name = String::EMPTY;
+ value = String::EMPTY;
+ try
+ {
+ //
+ // Parse each line of Config file
+ //
+ _parseLine(line,lineNumber,name,value,log_file);
+ }
+ //
+ // catch all the exceptions if any thrown from parseLine
+ // - Accumulate all the errors from the config file
+ // - Report all errors if found when complete.
+ //
+ catch (Exception& e)
+ {
+ char line_num[10];
+ sprintf(line_num, "%d", lineNumber);
+ String msg(e.getMessage());
+ ErrReports.append("\n ");
+ ErrReports.append("line#");
+ ErrReports.append(line_num);
+ ErrReports.append(":: ");
+ ErrReports.append(msg.getCString());
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<"::"
+ <<msg<<endl;
+ isSuccess = false;
+ }
+ catch(...)
+ {
+ char line_num[10];
+ sprintf(line_num, "%d", lineNumber);
+ ErrReports.append("\n ");
+ ErrReports.append("line#");
+ ErrReports.append(line_num);
+ ErrReports.append(":: ");
+ ErrReports.append("Unknown exception caught.");
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ ":Unknown exception caught when parsing line."<<endl;
+ cerr<<StressTestControllerCommand::COMMAND_NAME <<
+ ":Unknown exception caught when parsing line."<<endl;
+ return false;
+ }
+
+ if ((IsClientOptions)||(IgnoreLine))
+ {
+ IsClientOptions = false;
+ IgnoreLine = false;
+ continue;
+ }
+ //
+ // If its a client Update the table
+ //
+ if (IsAClient)
+ {
+ _currClient=name;
+ _currClientCount=_clientCount;
+ //
+ // save the client details in a table
+ //
+ if (!_storeClientDetails(name,value))
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Syntax error found in line#"<<lineNumber<<
+ " of config file: "<<fileName<<endl;
+ isSuccess = false;
+ }
+ }
+ else
+ {
+ //
+ // Common properties are updated only if they are valid.
+ //
+ if (isSuccess)
+ {
+ //
+ // Store the property name and value in the table
+ //
+ if (verboseEnabled)
+ {
+ cout<<" "<<name<<"\t= "<<value<<endl;
+ }
+ if (!_propertyTable->insert(name, value))
+ {
+ //
+ // Duplicate property, ignore the new property value.
+ //
+#ifdef DEBUG
+ cout<< "Property Name:duplicate name already saved: "<<
+ name<<endl;
+#endif
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Duplicate property name "<<name<<" already saved."<<
+ endl;
+ }
+ }
+ }
+
+ }
+ ifs.close();
+ //
+ // If a client is not read from the config file
+ //
+ if ((lineNumber==0)||(!_clientCount))
+ {
+ ErrReports.append("\n ");
+ ErrReports.append(StressTestControllerCommand::COMMAND_NAME);
+ ErrReports.append("::No clients found.");
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::No clients found in"<<" config file: "<<fileName<<endl;
+ isSuccess = false;
+ }
+ //
+ // Error was found.
+ //
+ if (!isSuccess)
+ {
+ //
+ // cleanup allocated memory
+ //
+ cleanupProcess();
+ throw StressTestControllerException(ErrReports);
+ }
+
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Common Properties:"<<endl;
+ if (verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Common Properties:"<<endl;
+ }
+ for (Table::Iterator i = _propertyTable->start(); i; i++)
+ {
+ log_file<<" "<<i.key()<<"\t= "<<i.value()<<endl;
+ if (verboseEnabled)
+ {
+ cout<<" "<<i.key()<<"\t= "<<i.value()<<endl;
+ }
+ }
+ if (verboseEnabled)
+ {
+ cout<<"Total clients found:"<<_clientCount<<endl;
+ cout<<"CLIENT TABLE CONTENTS:"<<endl;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Client Properties:"<<endl;
+ for (Uint32 j = 0; j < _clientCount; j++)
+ {
+ log_file<<"Client information #"<<j+1<<" from config file:"<<endl;
+ if (verboseEnabled)
+ {
+ cout<<"Client("<<j<<")"<<endl;
+ }
+ for (Table::Iterator i = _clientTable[j].start(); i; i++)
+ {
+ log_file<<" "<<i.key()<<" = "<<i.value()<<endl;
+ if (verboseEnabled)
+ {
+ cout<<" "<< i.key() << "=" << i.value() << endl;
+ }
+ }
+ }
+
+
+ if (isSuccess)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Successfully retreived config values from" <<
+ " config file: "<<fileName<<endl;
+ }
+ return isSuccess;
+}/* getFileContent */
+
+
+/*
+ Validates the configuration data found in the specified config file or
+ the default config file.
+ Will validate known common/client specific properties in configuration.
+ Will validate valid client names.
+ (Clients are excepted to exist in the $PEGASUS_HOME/bin directory)
+
+ @param vars The property name to be validated
+ @param value The property value associated to the above name
+
+ @return true if the property was validated successfully
+ false if the property failed validation.
+
+ */
+
+
+Boolean StressTestControllerCommand::_validateConfiguration(
+ String & vars,
+ const String & value,
+ ostream& log_file)
+{
+ Boolean IsValid = false;
+
+
+ if (String::equalNoCase(vars,HOSTNAME))
+ {
+ vars=String::EMPTY;
+ vars.append(HOSTNAME);
+ if(!IsAClient)
+ {
+ if (!_hostNameSpecified)
+ {
+ _hostName = value;
+ }
+ }
+ else
+ {
+
+ if(_hostName != String::EMPTY)
+ {
+ if (!String::equalNoCase(value,_hostName))
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Multiple hostnames were found. "<<endl;
+ if (verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Multiple hostnames were found. "<<endl;
+ }
+ return false;
+ }
+ }
+ else
+ {
+ _hostName = value;
+ }
+ }
+ }
+ else if (String::equalNoCase(vars,PORTNUMBER))
+ {
+ vars=String::EMPTY;
+ vars.append(PORTNUMBER);
+ Uint32 vPortNumber = atoi(value.getCString());
+
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Portnumber specified in config = "<<vPortNumber<<endl;
+ if (verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Portnumber specified in config = "<<vPortNumber<<endl;
+ }
+ if (vPortNumber > _MAX_PORTNUMBER)
+ {
+ //
+ // Portnumber out of valid range
+ //
+ if (verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Invalid portnumber was found. "<<endl;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Invalid portnumber was found. "<<endl;
+ return false;
+ }
+ if (!_portNumberSpecified)
+ {
+ _portNumber = atoi(value.getCString());
+ }
+
+ }/* else if (String::equalNoCase ... */
+ else if (String::equalNoCase(vars,SSL))
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::SSL enabled in config. "<<endl;
+ if (!_useSSL)
+ {
+ _useSSL = true;
+ }
+ }
+ else if (String::equalNoCase(vars,USERNAME))
+ {
+ vars=String::EMPTY;
+ vars.append(USERNAME);
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::UserName specified in config = "<<value<<endl;
+ if (!_userNameSpecified)
+ {
+ _userName = value;
+ }
+ }
+ else if (String::equalNoCase(vars,PASSWORD))
+ {
+ vars=String::EMPTY;
+ vars.append(PASSWORD);
+ if(!_passwordSpecified)
+ {
+ _password = value;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Password specified in config = "<<value<<endl;
+ }
+ else if (String::equalNoCase(vars,DURATION))
+ {
+ vars=String::EMPTY;
+ vars.append(DURATION);
+ //
+ // converting to a double
+ //
+ if (!IsAClient)
+ {
+ _duration = atof(value.getCString());
+ if (_duration > _MIN_DURATION)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Duration specified in config = "<<value<<endl;
+ }
+ else
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Invalid Duration was specified. "<<endl;
+ return false;
+ }
+ }
+ }
+ else if (String::equalNoCase(vars,TOLERANCELEVEL))
+ {
+ _toleranceLevel = atoi(value.getCString());
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::ToleranceLevel specified in config = "<<value<<endl;
+ if (_toleranceLevel > _MAX_TOLERANCE)
+ {
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Invalid Tolerance level was specified. "<<endl;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Invalid Tolerance level was specified. "<<endl;
+
+ return false;
+ }
+ }
+ else if (String::equalNoCase(vars,NAMESPACE))
+ {
+ _nameSpace = value;
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::NameSpace specified in config = "<<value<<endl;
+ }
+ else if (String::equalNoCase(vars,CLASSNAME))
+ {
+ _className = value;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Class name specified in config = "<<value<<endl;
+ }
+ else
+ {
+ if (!IsAClient)
+ {
+ IsAClient=true;
+ int instance = atoi(value.getCString());
+ //
+ // Check if the instances are set correctly
+ // Must be greater than 0
+ //
+ if (instance <=0)
+ {
+ //
+ // Invalid Instance value
+ //
+ return false;
+ }
+ //
+ // Check if client exists or is valid.
+ // Clients are expected to be in the $PEGASUS_HOME/bin directory
+ //
+ String clientName = String(DEFAULT_BINDIR);
+ clientName.append(vars.getCString());
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ clientName.append(".exe");
+#endif
+ if (!FileSystem::exists(clientName))
+ {
+ String testString = String::EMPTY;
+ testString.append("Test");
+ Uint32 Index = vars.find(testString);
+ if (Index != 0)
+ {
+ clientName = String(DEFAULT_BINDIR);
+ testString.append(vars.getCString());
+ clientName.append(testString.getCString());
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ clientName.append(".exe");
+#endif
+ if (!FileSystem::exists(clientName))
+ {
+ //
+ // Invalid client name
+ //
+ IsValid = false;
+ }
+ else
+ {
+ IsValid = true;
+ vars=String::EMPTY;
+ vars.append(testString.getCString());
+ }
+ }
+ else
+ {
+
+ //
+ // Invalid client name
+ //
+ IsValid = false;
+ }
+ }
+ else
+ {
+ IsValid = true;
+ }
+ if (!IsValid)
+ {
+ if (verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Invalid Client Name = "<<vars<<endl;
+ }
+ String ErrReport = String("Invalid Client Name:");
+ ErrReport.append(vars.getCString());
+ throw StressTestControllerException(ErrReport);
+ }
+ return IsValid;
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<"::"<<vars<<
+ " = "<<value<<endl;
+ //
+ // otherwise accept the properties listed with the clients.
+ //
+ }
+ return true;
+
+} /* _validateConfiguration */
+
+/*
+ Retrieves the client specific options from the config file.
+ Will check for syntax errors with the client options.
+ - Will retrieve all the client options in the line until ']'
+ - Client options/properties in Config file are
+ represented as follows:
+ - "[" indicates start of client options.
+ - "]" indicates end of client options.
+ - Client properties and values are seperated by commas.
+ Example:
+ [clientName=CLI,Options=niall]
+ - This method will throw appropriate exceptions.
+
+ @param p The pointer to the char in the concerned line
+
+
+ */
+void StressTestControllerCommand::_getClientOptions(
+ const Char16* p,
+ ostream& log_file)
+{
+ //
+ // Get the property name
+ //
+ String name = String::EMPTY;
+ String value = String::EMPTY;
+
+ while (*p != ']')
+ {
+ //
+ // Skip whitespace after property name
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+ if (!(isalpha(*p) || *p == '_'))
+ {
+ throw StressTestControllerException(StressTestControllerException::INVALID_OPTION);
+ }
+
+ name.append(*p++);
+
+
+ while (isalnum(*p) || *p == '_')
+ {
+ name.append(*p++);
+ }
+
+ //
+ // Skip whitespace after property name
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Expect an equal sign
+ //
+ if (*p != '=')
+ {
+ throw StressTestControllerException(StressTestControllerException::INVALID_OPERATOR);
+ }
+
+ p++;
+
+ //
+ // Skip whitespace after equal sign
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Get the value
+ //
+
+ while (*p && *p != ']' && *p != ',')
+ {
+ value.append(*p++);
+ }
+ //
+ // Skip whitespace after value
+ //
+ while (*p && isspace(*p))
+ {
+ cout << "got space after value\n";
+ p++;
+ }
+
+ if(*p !=']' && *p != ',')
+ {
+ throw StressTestControllerException(StressTestControllerException::MISSING_BRACE);
+ }
+ if(value == String::EMPTY)
+ {
+ throw StressTestControllerException(StressTestControllerException::MISSING_VALUE);
+ }
+
+#ifdef DEBUG
+ cout<<"name="<<name<<endl;
+ cout<<"Before validate config: value="<<value<<endl;
+#endif
+ //
+ // validate client property
+ //
+ Boolean IsValid=_validateConfiguration(name,value,log_file);
+ if(!IsValid)
+ {
+ String ErrReport = String("Invalid Client property value: ");
+ ErrReport.append(name);
+ ErrReport.append("=");
+ ErrReport.append(value);
+ throw StressTestControllerException(ErrReport);
+ }
+ //
+ // Save client property in client table if valid.
+ //
+ if (!_clientTable[_currClientCount].insert(name,value))
+ {
+ //
+ // Duplicate property, ignore the new property value.
+ // Log this message in a log file.
+ //
+ log_file<< "duplicate name already saved: "<<name<<endl;
+ if (verboseEnabled)
+ {
+ cout<< "duplicate name already saved: "<<name<<endl;
+ }
+ }
+ if (*p ==',')
+ {
+ name = String::EMPTY;
+ value = String::EMPTY;
+ p++;
+ continue;
+ }
+ }
+
+ if ((name == String::EMPTY)||(value == String::EMPTY))
+ {
+ String ErrReport = String("Missing Name & Value for client option:");
+ throw StressTestControllerException(ErrReport);
+ }
+} /* _getClientOptions */
+
+
+/*
+ Retrieves the Client PIDs and the corresponding status of the
+ clients started by the Controller from the PID file.
+ Each line in the PID file if not a comment is expected to
+ have the following format:
+ <clientid>::<client_pid>::<client_status>::<timeStampInMillisec>
+ Example:
+ 1::7582::0::4119329327
+
+ Client PID, status and Time Stamp from the PID file will be saved
+ in the following global array's for each client.
+ clientPIDs
+ clientStatus
+ clientTimeStamp
+
+
+ @param actual_clients The actual number of clients executed by the
+ Controller.
+ @param log_file The log file.
+
+ @return true if the status and PIDs were read successfully
+ false Failed to read the status & PIDs of clients.
+
+ */
+Boolean StressTestControllerCommand::_getClientPIDs(
+ int actual_clients,
+ ostream& log_file)
+{
+
+ ifstream ifs;
+
+ //
+ // Make a temp copy of the file
+ //
+ Boolean cTempFile = FileSystem::copyFile(
+ _stressTestClientPIDFile,
+ _tmpStressTestClientPIDFile);
+
+ if(!cTempFile)
+ {
+ cout<<"Cannot copy file "<<_stressTestClientPIDFile<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Cannot copy PID file: "<<_stressTestClientPIDFile<<endl;
+ return (false);
+ }
+ //
+ // Open the temp PID file and retreive all the client PIDs and status
+ //
+ Open(ifs,_tmpStressTestClientPIDFile);
+
+ String line;
+
+ const Char16* p;
+ int lineNumber= 0;
+ Boolean isSuccess=false;
+ //
+ // get each line until end of file.
+ //
+ while (GetLine(ifs, line))
+ {
+ ++lineNumber;
+#ifdef DEBUG
+ log_file<<" Line number:"<<lineNumber<<endl;
+ log_file<<" "<<line<<endl;
+#endif
+ p = line.getChar16Data();
+
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Skip comment lines
+ //
+ if ((!*p)||(*p == '#'))
+ {
+ continue;
+ }
+
+ //
+ // Get the client ID
+ //
+ String client = String::EMPTY;
+ while (isalnum(*p) || *p == '_')
+ {
+ client.append(*p++);
+ }
+
+ //
+ // Skip whitespace after property name
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Expecting a colon
+ //
+ if (*p != ':')
+ {
+ ifs.close();
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Syntax Error in PID file line number:"<<lineNumber<<endl;
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = false);
+ }
+
+ //
+ // point to next character in line.
+ //
+ p++;
+
+ //
+ // Expecting a colon
+ //
+ if (*p != ':')
+ {
+ ifs.close();
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Syntax Error in PID file line number:"<<lineNumber<<endl;
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = false);
+ }
+
+ //
+ // point to next character in line.
+ //
+ p++;
+
+ //
+ // Skip whitespace after colon
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Get the client PID
+ //
+ String clntPID = String::EMPTY;
+ while (isalnum(*p) || *p == '_')
+ {
+ clntPID.append(*p++);
+ }
+
+ //
+ // Skip whitespace after property name
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Expecting a colon
+ //
+ if (*p != ':')
+ {
+ ifs.close();
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Syntax Error in PID file line number:"<<lineNumber<<endl;
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = false);
+ }
+
+ //
+ // point to next character in line.
+ //
+ p++;
+
+ //
+ // Expecting a colon
+ //
+ if (*p != ':')
+ {
+ ifs.close();
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Syntax Error in PID file line number:"<<lineNumber<<endl;
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = false);
+ }
+ p++;
+
+ //
+ // Skip whitespace after the colon if any
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ String clntStatus = String::EMPTY;
+ while (isalnum(*p) || *p == '_')
+ {
+ clntStatus.append(*p++);
+ }
+
+ //
+ // Skip whitespace after property name
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Expecting a colon
+ //
+ if (*p != ':')
+ {
+ ifs.close();
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ "::Syntax Error in PID file line number:"<<lineNumber<<endl;
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = false);
+ }
+
+ //
+ // next character in line.
+ //
+ p++;
+
+ if (*p != ':')
+ {
+ ifs.close();
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Syntax Error in PID file line number:"<<lineNumber<<endl;
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = false);
+ }
+ //
+ // next character in line.
+ //
+ p++;
+ //
+ // Skip whitespace after the colon if any
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Get the client timestamp
+ //
+ String clntTmStmp = String::EMPTY;
+ while (isalnum(*p))
+ {
+ clntTmStmp.append(*p++);
+ }
+
+ //
+ // Store the PID, Status and TimeStamp for each client
+ //
+ if(atoi(client.getCString()) <= actual_clients)
+ {
+ clientPIDs[atoi(client.getCString())] =
+ (pid_t)atoi(clntPID.getCString());
+ clientStatus[atoi(client.getCString())] =
+ (pid_t)atoi(clntStatus.getCString());
+ sscanf(
+ (const char*)clntTmStmp.getCString(),
+ "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
+ &clientTimeStamp[atoi(client.getCString())]);
+ }
+ else
+ {
+ if (verboseEnabled)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Unknown client PID for client#"<<
+ atoi(client.getCString())<<
+ " read at line number:"<<lineNumber<<endl;
+ cout<<"Unknown Client PID recieved"<<endl;
+ }
+ }
+ }
+ //
+ // remove the temporary file.
+ //
+ FileSystem::removeFile(_tmpStressTestClientPIDFile);
+ return(isSuccess = true);
+}/* _getClientPIDs */
+
+/*
+ Parses specified line to retrieve valid config data for the stress tests.
+ - Identifies client specific properties from common properties in config file
+ - Saves all the client specific data from the config file into appropriate
+ client tables.
+ - Saves all the common properties in the property table
+ - This method will throw appropriate exceptions.
+ Config File Format:
+ - All comments begin with "#"
+ - Properties in Config file are represented as follows:
+ <property> = <property value>
+ - Client options/properties in Config file are
+ represented as follows:
+ - "[" indicates start of client options.
+ - Client properties and values are seperated by commas.
+ Example:
+ [clientName=CLI,Options=niall]
+
+ @param line The line that will be parsed.
+ @parm lineNumber The line number of the line.
+ @parm name The property name that will be retrieved.
+ @parm value The property value of the name.
+ @parm log_file The log file.
+
+ @return true Succesfully parsed the line.
+ false Failed to parse the lines successfully.
+ */
+Boolean StressTestControllerCommand::_parseLine(
+ const String & line,
+ int lineNumber,
+ String &name,
+ String &value,
+ ostream& log_file)
+{
+
+ const Char16* p;
+ p = line.getChar16Data();
+
+ //
+ // Skip whitespace
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Ignore empty lines
+ //
+ if (!*p)
+ {
+ IgnoreLine = true;
+ return IgnoreLine;
+ }
+
+ //
+ // Skip comment lines
+ //
+ if (*p == '#')
+ {
+ IgnoreLine = true;
+ return IgnoreLine;
+ }
+
+ //
+ // Retreive all the Client Options
+ // "[" indicates start of client options.
+ //
+ if (*p == '[')
+ {
+ IsAClient = true;
+ IsClientOptions = true;
+ p++;
+ //
+ // Ignore spaces before client property
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+ //
+ // Invalid Client property name
+ //
+ if (!(isalpha(*p) || *p == '_'))
+ {
+ String ErrReport = String("Syntax Error with client options:");
+ ErrReport.append(line.getCString());
+ throw StressTestControllerException(ErrReport);
+ }
+ //
+ // Retrieve client options
+ //
+ try
+ {
+ //
+ // get and validate client options
+ //
+ _getClientOptions(p,log_file);
+ }
+ catch (Exception& e)
+ {
+ String msg(e.getMessage());
+ if ((name == String::EMPTY)
+ ||(value == String::EMPTY))
+ {
+ msg.append(" in ");
+ msg.append(line.getCString());
+ }
+ throw StressTestControllerException(msg);
+ }
+ catch (...)
+ {
+ String msg = String(
+ "Unknown exception caught when geting client options.");
+ log_file<<StressTestControllerCommand::COMMAND_NAME <<
+ ":Unknown exception caught when geting client options."<<endl;
+ cerr<<StressTestControllerCommand::COMMAND_NAME <<
+ ":Unknown exception caught when geting client options."<<endl;
+ throw StressTestControllerException(msg);
+ }
+
+ //
+ // Successfully retrieved all the client options.
+ //
+ return true;
+ }
+
+ //
+ // Get Common Properties
+ //
+ name = String::EMPTY;
+
+ //
+ // Invalid Common Property name
+ //
+ if (!(isalpha(*p) || *p == '_'))
+ {
+ String ErrReport = String("Invalid Property Value: ");
+ ErrReport.append(name);
+ ErrReport.append("=");
+ ErrReport.append(value);
+ throw StressTestControllerException(ErrReport);
+ }
+
+ //
+ // Save the property Name
+ //
+ name.append(*p++);
+ while (isalnum(*p) || *p == '_')
+ {
+ name.append(*p++);
+ }
+
+ //
+ // Skip whitespace after property name
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Expect an equal sign
+ //
+ if (*p != '=')
+ {
+ String ErrReport = String("Invalid Property Value: ");
+ ErrReport.append(name);
+ ErrReport.append("=");
+ ErrReport.append(value);
+ throw StressTestControllerException(ErrReport);
+ }
+
+ //
+ // go to next
+ //
+ p++;
+
+ //
+ // Retrive the property value
+ // Skip whitespace after equal sign
+ //
+ while (*p && isspace(*p))
+ {
+ p++;
+ }
+
+ //
+ // Get the value
+ //
+ value = String::EMPTY;
+ while (*p)
+ {
+ value.append(*p++);
+ }
+#ifdef DEBUG
+ cout<<"name="<<name<<endl;
+ cout<<"value="<<value<<endl;
+#endif
+ IsAClient = false;
+ Boolean IsValid = false;
+ //
+ // Validate property and its value
+ //
+ try
+ {
+ IsValid=_validateConfiguration(name,value,log_file);
+ }
+ catch (Exception& e)
+ {
+ String msg(e.getMessage());
+ throw StressTestControllerException(msg);
+ }
+ if (!IsValid)
+ {
+ String ErrReport = String("Invalid Property Value: ");
+ ErrReport.append(name);
+ ErrReport.append("=");
+ ErrReport.append(value);
+ throw StressTestControllerException(ErrReport);
+ }
+ return true;
+} /* _parseLine */
+
+/*
+ Storing client details in a table.
+ - Stores the Client name and instance for specific clients in their
+ respective client table for later use.
+
+ @parm name The client name that will be stored.
+ @parm value The number of instances of the client.
+
+ @return true Succesfully stored the name or instance.
+ false Failed to store the name or instance.
+ */
+Boolean StressTestControllerCommand::_storeClientDetails(
+ String name,
+ String value)
+{
+
+ //
+ // Expand the client table as required.
+ //
+ if (_clientCount >= Total_Clients)
+ {
+ Total_Clients += NEW_CLIENTS;
+ Table* tempClientTable = new Table[Total_Clients];
+ for (Uint32 i =0;i<_clientCount;i++)
+ {
+ tempClientTable[i] = _clientTable[i];
+ }
+ delete [] _clientTable;
+ _clientTable = tempClientTable;
+ }
+
+ //
+ // Store the client Name in the table
+ //
+ if (!_clientTable[_clientCount].insert(NAME, name))
+ {
+ //
+ // Duplicate property, ignore the new property value.
+ //
+ if (verboseEnabled)
+ {
+ cout<< "Duplicate Client already saved: "<<endl;
+ }
+ return false;
+ }
+
+ //
+ // Store the number of instances for the client in the table
+ //
+ if (!_clientTable[_clientCount].insert(INSTANCE, value))
+ {
+
+ //
+ // Duplicate property, ignore the new property value.
+ //
+ if(verboseEnabled)
+ {
+ cout<< "Duplicate Instance already saved: "<<endl;
+ }
+ return false;
+ }
+ ++_clientCount;
+ return true;
+} /* _storeClientDetails */
+
+/*
+ Will check the current tolerance level of the running clients with
+ respect to the expected tolerance level.
+ @parm actual_client The total number of executed clients.
+ @parm nowMilliseconds The current time in milliseconds.
+ @parm log_file The log_file.
+
+ @return true Clients with tolerance.
+ false Clients failed tolerance.
+ */
+Boolean StressTestControllerCommand::_checkToleranceLevel(
+ int actual_client,
+ Uint64 nowMilliseconds,
+ ostream& log_file)
+{
+ int count = 0;
+ int failed_count = 0;
+ Uint64 lastUpdateinMilliSec =0;
+ Boolean withinTolerance = false;
+
+ for (int i=0;i<actual_client;i++)
+ {
+ //
+ //Observe only the status of running clients
+ //
+ if (clientActive[i])
+ {
+ ++count;
+ //
+ // Validate the timestamps:
+ // The timestamps on the status is compared to the previous
+ // timestamp to ensure that the status has been updated within
+ // the previous 2 updates.
+ //
+ if(clientStatus[i]== VALID_RESPONSE)
+ {
+ //
+ //check with the last timestamp
+ //
+ lastUpdateinMilliSec = nowMilliseconds - clientTimeStamp[i];
+ //
+ // Assume failure if status update is
+ // longer than 2 * checkup interval
+ //
+ if ((clientTimeStamp[i] == prev_clientTimeStamp[i])
+ && (lastUpdateinMilliSec >=
+ (2 * (Uint64)convertmin2millisecs(CHECKUP_INTERVAL))))
+ {
+ if (verboseEnabled)
+ {
+ log_file <<" Status not updated for client (" <<i<<
+ ")pid :"<<clientPIDs[i]<<endl;
+ log_file << " for the past " <<
+ 2*(CHECKUP_INTERVAL) << " minutes." << endl;
+ cout<<" Status not updated for client ("<<i<<")pid :"<<
+ clientPIDs[i]<<endl;
+ cout<<" for the past " << 2*(CHECKUP_INTERVAL)<<
+ " minutes." << endl;
+ }
+ ++failed_count;
+ }
+ }
+ //
+ // If unknown status - server or client may be hung.
+ // Two consective failures on the same client will be counted
+ // as a failed client.
+ //
+ if (((clientStatus[i]== NO_RESPONSE)
+ ||(clientStatus[i]== INVALID_RESPONSE))
+ &&((prev_clientStatus[i]== NO_RESPONSE)
+ ||(prev_clientStatus[i]== INVALID_RESPONSE)))
+ {
+ if (verboseEnabled)
+ {
+ if (clientStatus[i]== INVALID_RESPONSE)
+ {
+ log_file<<
+ "Recieved an Invalid response Status from client("<<
+ i <<") pid :"<<clientPIDs[i]<<endl;
+ }
+ else
+ {
+ log_file<<"Recieved a no response Status from client("<<
+ i <<") pid :"<<clientPIDs[i]<<endl;
+ }
+ }
+ ++failed_count;
+ } /* if (((clientStatus[i]== NO_RESPONSE) ... */
+ //
+ // Save previous time stamp of client
+ //
+ prev_clientTimeStamp[i] = clientTimeStamp[i];
+ prev_clientStatus[i] = clientStatus[i];
+ } /* if (clientActive[i]) */
+ }
+ //
+ // check actual tolerance
+ //
+ if(count > 0)
+ {
+ double curr_tolerancePercent = getToleranceInPercent(
+ failed_count,
+ (double)count);
+ if (verboseEnabled)
+ {
+ cout<<" total running clients ="<<count<<endl;
+ cout<<" failed clients ="<<failed_count<<endl;
+ cout<<"Actual Tolerance % ="<<curr_tolerancePercent<<endl;
+ cout<<"Expected Tolerance % ="<<_toleranceLevel<<endl;
+ log_file<<"Total Running clients:"<<count<<endl;
+ log_file<<"Actual Failed clients:"<<failed_count<<endl;
+ log_file<<"::Expected Tolerance:"<<_toleranceLevel<<endl;
+ log_file<<"::Actual Tolerance:"<<curr_tolerancePercent<<endl;
+ }
+ if ((double)_toleranceLevel >= curr_tolerancePercent)
+ {
+ withinTolerance = true;
+ }
+ return(withinTolerance);
+ }
+ //
+ // All process are stopped.
+ //
+ return(withinTolerance = true);
+} /* _checkToleranceLevel */
+
+
+/*
+ This will populate the client table with the hard coded
+ values for the stress tests.
+ This method is only used if the default configuration
+ file does not exist.
+ Default clients are 5 instances of
+ "TestWrapperStressClient" and "TestModelWalkStressClient".
+
+ @parm log_file The log_file.
+
+ */
+void StressTestControllerCommand::getDefaultClients(ostream& log_file)
+{
+ //
+ // Setting the client count to default client value
+ //
+ _clientCount = DEFAULT_CLIENTS;
+
+ log_file << "Populating default configuration for stress Tests." << endl;
+ if (verboseEnabled)
+ {
+ cout << "Populating default configuration for stress Tests." << endl;
+ }
+ //
+ // Populating default client attributes
+ //
+ for (Uint32 i=0;i<_clientCount; i++)
+ {
+ //
+ // Adding the default instance value to each client table
+ //
+ if (!_clientTable[i].insert(INSTANCE, DEFAULT_INSTANCE))
+ {
+ log_file << "Duplicate name already saved: "<<INSTANCE<<endl;
+ if (verboseEnabled)
+ {
+ cout<< "duplicate name already saved: "<<INSTANCE<<endl;
+ }
+ }
+ switch(i)
+ {
+ case 0:
+ {
+ if (!_clientTable[i].insert(NAME, MODELWALK_CLIENT))
+ {
+ log_file << "Duplicate name already saved: "<<NAME<<endl;
+ if (verboseEnabled)
+ {
+ cout<< "Duplicate name already saved: "<<NAME<<endl;
+ }
+ }
+ log_file << "Stress Test Client Name:"<<MODELWALK_CLIENT<< endl;
+ if (verboseEnabled)
+ {
+ cout<< "Stress Test Client Name:"<<MODELWALK_CLIENT<< endl;
+ }
+
+ break;
+ }
+ case 1:
+ {
+ if (!_clientTable[i].insert(NAME, WRAPPER_CLIENT))
+ {
+ log_file << "Duplicate name already saved: "<<NAME<<endl;
+ if (verboseEnabled)
+ {
+ cout<< "Duplicate name already saved: "<<NAME<<endl;
+ }
+ }
+ log_file << "Stress Test Client Name:" <<WRAPPER_CLIENT<< endl;
+ if (verboseEnabled)
+ {
+ cout << "Stress Test Client Name:" <<WRAPPER_CLIENT<< endl;
+ }
+ if (!_clientTable[i].insert(CLIENTNAME, "CLI"))
+ {
+ log_file<< "Duplicate name already saved: "<<
+ CLIENTNAME<<endl;
+ if (verboseEnabled)
+ {
+ cout<< "Duplicate name already saved: "<<
+ CLIENTNAME<<endl;
+ }
+ }
+ if (!_clientTable[i].insert(OPTIONS, "niall"))
+ {
+ log_file<< "Duplicate name already saved: "<<OPTIONS<<endl;
+ if (verboseEnabled)
+ {
+ cout<< "Duplicate name already saved: "<<OPTIONS<<endl;
+ }
+ }
+ log_file<< " Client Command & options: CLI niall"<<
+ endl;
+ if (verboseEnabled)
+ {
+ cout<< " Client Command & options: CLI niall"<<
+ endl;
+ }
+ break;
+ } /* case 1: */
+ } /* switch(i) */
+ } /* for(Uint32 i=0;i<_clientCount; i++) */
+
+} /* getDefaultClients */
+
+
+
+
+/**
+ Will generate or create all the required files for the tests.
+ - Required log files, pid files, client log file are created here.
+
+ @parm strTime The time stamp for the tests.
+ This is used in the naming of the log file.
+
+ @return true The files were successfully created.
+ false Failed to create one or more of the required
+ files.
+
+ */
+Boolean StressTestControllerCommand::generateRequiredFileNames(char *strTime)
+{
+ char pid_str[15];
+ ofstream log_file;
+ ofstream pid_file;
+ ofstream clntlog_file;
+
+ sprintf(pid_str, "%d", getpid());
+
+ //
+ // Stress Controller Log file
+ //
+ _stressTestLogFile.append(pegasusHome);
+ _stressTestLogFile.append(TESTDIR);
+ FileSystem::makeDirectory(_stressTestLogFile);
+ _stressTestLogFile.append(STRESSTESTDIR);
+ FileSystem::makeDirectory(_stressTestLogFile);
+ _stressTestLogFile.append(LOGDIR);
+ FileSystem::makeDirectory(_stressTestLogFile);
+ _stressTestLogFile.append(pid_str);
+ _stressTestLogFile.append("_stressTest_");
+ _stressTestLogFile.append(strTime);
+ _stressTestLogFile.append("log");
+
+ //
+ // StressClient PID file
+ //
+ _stressTestClientPIDFile.append(pegasusHome);
+ _stressTestClientPIDFile.append(DEFAULT_TMPDIR);
+ FileSystem::makeDirectory(_stressTestClientPIDFile);
+ _stressTestClientPIDFile.append(pid_str);
+ _stressTestClientPIDFile.append("_StressTestClients");
+ _stressTestClientPIDFile.append(strTime);
+ _stressTestClientPIDFile.append("pid");
+
+ //
+ // StressClient Log file
+ //
+ _stressTestClientLogFile.append(pegasusHome);
+ _stressTestClientLogFile.append(DEFAULT_LOGDIR);
+ _stressTestClientLogFile.append(pid_str);
+ _stressTestClientLogFile.append("_StressTestClients");
+ _stressTestClientLogFile.append(".log");
+
+ //
+ // Temporary StressClient PID/status file
+ //
+ _tmpStressTestClientPIDFile.append(pegasusHome);
+ _tmpStressTestClientPIDFile.append(DEFAULT_TMPDIR);
+ _tmpStressTestClientPIDFile.append(pid_str);
+ _tmpStressTestClientPIDFile.append("TEMP");
+ _tmpStressTestClientPIDFile.append("_Clients");
+ _tmpStressTestClientPIDFile.append(".pid");
+
+ //
+ // Translate slashed for appropriate OS
+ //
+ FileSystem::translateSlashes(_stressTestClientPIDFile);
+ FileSystem::translateSlashes(_stressTestClientLogFile);
+ FileSystem::translateSlashes(_stressTestLogFile);
+ FileSystem::translateSlashes(_tmpStressTestClientPIDFile);
+
+ //
+ // open the file
+ //
+ OpenAppend(log_file,_stressTestLogFile);
+ Open(pid_file,_stressTestClientPIDFile);
+ Open(clntlog_file,_stressTestClientLogFile);
+
+ //
+ // Failed to open the log file
+ //
+ if (!log_file)
+ {
+ log_file.close();
+ pid_file.close();
+ clntlog_file.close();
+ cout<<"Cannot get file "<<_stressTestLogFile<<endl;
+ return false;
+
+ }
+ //
+ // Failed to open the pid file
+ //
+ if (!pid_file)
+ {
+ cout<<"Cannot get file "<<_stressTestClientPIDFile<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "Cannot read file "<<_stressTestClientPIDFile<<endl;
+ log_file.close();
+ clntlog_file.close();
+ return false;
+ }
+ //
+ // Failed to open the clntlog file
+ //
+ if (!clntlog_file)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "Cannot read file "<<_stressTestClientLogFile<<endl;
+ log_file.close();
+ pid_file.close();
+ return false;
+ }
+
+ //
+ // Successfully opened all the files.
+ //
+ pid_file<<"#"<<StressTestControllerCommand::COMMAND_NAME<<
+ " has the following clients:: \n";
+ clntlog_file<<"#"<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Process ID:"<<getpid()<<endl;
+ clntlog_file.close();
+ pid_file.close();
+ return true;
+
+} /* generateRequiredFileNames */
+
+/**
+ Will remove all the unused files for the tests.
+ - Unused log files & pid files are removed here.
+
+ */
+void StressTestControllerCommand::removeUnusedFiles()
+{
+ FileSystem::removeFile(_stressTestClientPIDFile);
+ FileSystem::removeFile(_stressTestClientLogFile);
+}
+
+PEGASUS_NAMESPACE_END
+
+/**
+ Cleanup function for stressTestController to free allocated
+ memory used to execute clients.
+ */
+void cleanupProcess()
+{
+
+ delete [] clientPIDs;
+ delete [] clientStatus;
+ delete [] clientInstance;
+ delete [] clientActive;
+ delete [] clientTimeStamp;
+ delete [] prev_clientTimeStamp;
+ delete [] prev_clientStatus;
+}
+
+/*
+ This will generate the current time.
+ */
+struct tm getCurrentActualTime()
+{
+ struct tm tmTime;
+ time_t inTime=time(NULL);
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ tmTime=*localtime(&inTime);
+#else
+ localtime_r(&inTime,&tmTime);
+#endif
+ return tmTime;
+}
+
+/**
+ Signal handler for SIGINT, SIGABRT.
+
+ @param signum the signal identifier
+*/
+void endAllTests(int signum)
+{
+ if (verboseEnabled)
+ {
+ switch(signum)
+ {
+ case SIGINT:
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Recieved interupt signal SIGINT!"<<endl;
+ break;
+ }
+ case SIGABRT:
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Recieved signal SIGABRT!"<<endl;
+ break;
+ }
+ default:
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Recieved Signal ( "<<signum<<"!" <<endl;
+ break;
+ }
+ }
+ }
+ //
+ // Sets the variable that will interupt stress tests
+ //
+ Quit = true;
+} /* endAllTests */
+
+/**
+ This function will convert a Uint64
+ to a string.
+
+ @param x The Uint64 integer
+
+ @return String Returns the converted string.
+*/
+String convertUint64toString(Uint64 x)
+{
+ char buffer[32];
+ sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", x);
+ return(String(buffer));
+}/* convertUint64toString(..) */
diff --git a/test/StressTestController/StressTestController.h b/test/StressTestController/StressTestController.h
new file mode 100644
index 0000000..a6d74f0
--- /dev/null
+++ b/test/StressTestController/StressTestController.h
@@ -0,0 +1,551 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: John Alex (IBM)
+//
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#ifndef Pegasus_StressTestControllerCommand_h
+#define Pegasus_StressTestControllerCommand_h
+
+#include <Pegasus/Common/String.h>
+#include <Pegasus/Common/HashTable.h>
+#include <Clients/cliutils/Command.h>
+#include <Clients/cliutils/CommandException.h>
+
+struct tm getCurrentActualTime();
+
+PEGASUS_NAMESPACE_BEGIN
+
+////////////////////////////////////////////////////////////////////////////////
+// ConfigTable to contain the stressTest configurations
+////////////////////////////////////////////////////////////////////////////////
+typedef HashTable<String, String, EqualFunc<String>, HashFunc<String> > Table;
+
+/**
+ This constant signifies that an operation option has not been recorded.
+*/
+static const Uint32 OPERATION_TYPE_UNINITIALIZED = 0;
+
+/**
+ This constant represents a help operation.
+*/
+static const Uint32 OPERATION_TYPE_HELP = 1;
+
+/**
+ This constant represents a version display operation.
+*/
+static const Uint32 OPERATION_TYPE_VERSION = 2;
+
+
+static Boolean verboseEnabled = false;
+
+
+/**
+ The StressTestController command requires CIM Server to be
+ installed and running on the target host.
+
+ */
+class StressTestControllerCommand : public Command
+{
+public:
+
+ enum { DEFAULT_TIMEOUT_MILLISECONDS = 200000 };
+
+ /**
+
+ Constructs an StressTestControllerCommand and initializes
+ instance variables.
+
+ */
+
+ StressTestControllerCommand ();
+ /**
+
+ Parses the command line, validates the options, and sets instance
+ variables based on the option arguments.
+
+ @param argc the number of command line arguments
+ @param argv the string vector of command line arguments
+
+ @exception CommandFormatException if an error is encountered in
+ parsing the command line
+
+ */
+
+ void setCommand (Uint32 argc, char* argv []);
+
+ /**
+
+ Executes the command and writes the results to the PrintWriters.
+
+ @param outPrintWriter the ostream to which output should be
+ written
+ @param errPrintWriter the ostream to which error output should be
+ written
+
+ @return 0 if the command is successful
+ 1 if an error occurs in executing the command
+
+ */
+ Uint32 execute(ostream& outPrintWriter, ostream& errPrintWriter);
+
+ /**
+
+ Generates the actual commands for each of the test clients.
+
+ @return true if the commands are generated successfully
+ false if unsuccessful in generating commands.
+
+ */
+ Boolean generateClientCommands(ostream& log_file);
+
+ /**
+ Retrieves the config information from the stressController configuration
+ file.
+
+ @param filePath the filename itself may or may not include an
+ absolute path.
+ @return
+ */
+ Boolean getFileContent (String filePath,ostream& log_file);
+
+ /**
+ Retrieves the config file path name
+
+ @return _configFilePath The pathname is returned.
+
+ */
+ String getConfigFilePath(){ return _configFilePath;}
+
+ /**
+ Checks to verify if new pathname was opted.
+
+ @return true A path name was set.
+ false Use the default pathname.
+
+ */
+ Boolean IsConfigFilePathSpecified(){return _configFilePathSpecified;}
+
+ /**
+ Retrieves the command operation type
+
+ @return _operationType The operation type is returned.
+
+ */
+ Uint32 getOperationType(){return _operationType;}
+
+ /**
+ Populate test with default configuration values if default configuration file
+ is not found.
+
+ @return
+
+ */
+ void getDefaultClients(ostream& log_file);
+
+ /**
+ The command name.
+ */
+ static const char COMMAND_NAME [];
+
+
+ /**
+ Will generate or create all the required files for the tests.
+ Required log files, pid files etc are created here.
+
+ @parm strTime The time stamp for the tests.
+
+ @return
+
+ */
+ Boolean generateRequiredFileNames(char *strTime);
+
+ /**
+ Will remove all the unused files for the tests.
+ - Unused log files & pid files are removed here.
+
+ */
+ void removeUnusedFiles();
+
+ /**
+ Retrieves the stress Test log file path name.
+
+ @return StressTestLogFile The log filename is returned.
+
+ */
+ String getStressTestLogFile(){ return _stressTestLogFile;}
+ String getStressClientLogFile(){ return _stressTestClientLogFile;}
+
+ /**
+ Stress Test directories and files.
+ */
+ static char FILENAME[];
+ static char TESTDIR[];
+ static char STRESSTESTDIR[];
+ static char LOGDIR[];
+ static char BINDIR[];
+ static char DEFAULT_DIR[];
+ static char DEFAULT_CFGDIR[];
+ static char DEFAULT_LOGDIR[];
+ static char DEFAULT_TMPDIR[];
+
+ //
+ // Environment variable:
+ //
+ char* pegasusHome;
+
+private:
+
+ /**
+ Parses each line in the stressController config file.
+
+ @return true Parse was successful.
+ false Parsing resulted in a failure or invalid config.
+ */
+ Boolean _parseLine(
+ const String & string,
+ int line,
+ String & name,
+ String & value,
+ ostream& log_file);
+
+ /**
+ Stores client details from config file.
+
+ @return true Successfully retrieved and stored the details.
+ false Un-successfull.
+ */
+ Boolean _storeClientDetails(String name, String value);
+
+ /**
+ Validate StressTest configuration properties & clients.
+
+ @return true Successfully validated.
+ false Un-successfull.
+ */
+ Boolean _validateConfiguration(
+ String & var,
+ const String & value,
+ ostream& log_file);
+
+ /**
+ parse and save all the options for each client.
+
+ @return
+
+ */
+ void _getClientOptions(const Char16* p,ostream& log_file);
+
+ /**
+ Checks if the actual tolerance level of the current tests
+ are within expected tolerances.
+
+ @return true Within tolerance level
+ false Failed tolerance expectations.
+
+ */
+ Boolean _checkToleranceLevel(
+ int act_clients,
+ Uint64 nowMilliseconds,
+ ostream& log_file);
+
+ /**
+ Retrieves and stores client details from client pid file.
+
+ @return true Successfully retrieved and stored the details.
+ false Un-successfull.
+ */
+ Boolean _getClientPIDs(int clients,ostream& log_file);
+
+
+ /**
+ The host on which the command is to be executed. A CIM Server must be
+ running on this host when the command is executed. The default host is
+ the local host.
+ */
+ String _hostName;
+
+ /**
+ A Boolean indicating whether a hostname was specified on the command
+ line. The default host is the local host.
+ */
+ Boolean _hostNameSpecified;
+
+ /**
+ The timeout value to be used, in milliseconds.
+ The default timeout value is DEFAULT_TIMEOUT_MILLISECONDS.
+ */
+ Uint32 _timeout;
+
+
+ /**
+
+ The port to be used when the command is executed. The
+ port number must be the port number on which the
+ target CIM Server is running.
+
+ If no port is specified, StressTestController will attempt to locate
+ the port associated with the service "wbem-http" for non-SSL connections
+ and "wbem-https" for SSL connections. If not found, the DMTF
+ recommended default port number will be used.
+
+ _portNumberStr and _portNumber are not used with
+ connectLocal().
+
+ The default port for non-SSL 5988 and 5989 for SSL.
+
+ */
+ String _portNumberStr;
+ Uint32 _portNumber;
+ Uint32 _port; // JA not sure..if needed
+
+ /**
+ A Boolean indicating whether a port number was specified on the
+ command line.
+ */
+ Boolean _portNumberSpecified;
+
+ /**
+ The username to be used for authentication and
+ authorization of the operation.
+ */
+ String _userName;
+
+ /**
+ Indicates that the user name is set.
+ */
+ Boolean _userNameSpecified;
+
+ /**
+ The password to be used for authentication.
+ */
+ String _password;
+
+ /**
+ Indicates that the password is set.
+ */
+ Boolean _passwordSpecified;
+
+ /**
+ A Boolean indicating whether an SSL connection was specified on the
+ command line.
+ */
+ Boolean _useSSL;
+
+ /**
+ The duration of the stress tests
+ */
+ static double _duration;
+
+ /**
+ Indicates that the duration is set.
+ */
+ Boolean _durationSpecified;
+
+ /**
+ The ToleranceLevel used for the stress tests
+ */
+ Uint32 _toleranceLevel;
+
+ /**
+ Indicates that the toleranceLevel is set.
+ */
+ Boolean _toleranceLevelSpecified;
+
+ /**
+ The NameSpace that may be used by the clients
+ */
+ String _nameSpace;
+
+ /**
+ Indicates that the Name Space is set.
+ */
+ Boolean _nameSpaceSpecified;
+
+ /**
+ The Class Name that may be used by the clients
+ */
+ String _className;
+
+ /**
+ Indicates that the Class Name is set.
+ */
+ Boolean _ClassNameSpecified;
+
+
+ /**
+ The option character used to specify the hostname.
+ */
+ static const char _OPTION_HOSTNAME;
+
+ /**
+ The option character used to specify the port number.
+ */
+ static const char _OPTION_PORTNUMBER;
+
+ /**
+ The option character used to specify the timeout value.
+ */
+ static const char _OPTION_TIMEOUT;
+
+ /**
+ The option character used to specify the username.
+ */
+ static const char _OPTION_USERNAME;
+
+ /**
+ The option character used to specify the password.
+ */
+ static const char _OPTION_PASSWORD;
+
+ /**
+ The option character used to specify whether SSL should be used.
+ */
+ static const char _OPTION_SSL;
+
+ /**
+ Label for the usage string for this command.
+ */
+ static const char _USAGE [];
+
+ /**
+ The minimum valid portnumber.
+ */
+ static const Uint32 _MIN_PORTNUMBER;
+
+ /**
+ The maximum valid portnumber.
+ */
+ static const Uint32 _MAX_PORTNUMBER;
+
+ /**
+ The minimum valid duration level.
+ */
+ static const Uint32 _MIN_DURATION;
+
+ /**
+ The minimum valid tolerance level.
+ */
+ static const Uint32 _MIN_TOLERANCE;
+
+ /**
+ The maximum valid tolerance level.
+ */
+ static const Uint32 _MAX_TOLERANCE;
+
+ /**
+ The path of the config file containing the configuration info.
+ */
+ String _configFilePath;
+
+ /**
+ A Boolean indicating whether a config file path was specified on the
+ command line.
+ */
+ Boolean _configFilePathSpecified;
+
+ /**
+ A String containing the usage information for the command.
+ */
+ String _usage;
+
+ /**
+ The type of operation specified on the command line.
+ */
+ Uint32 _operationType;
+
+ /**
+ Property table that stores the properties
+ */
+ Table* _propertyTable;
+
+ /**
+ Client table that stores the client specific properties
+ */
+ Table* _clientTable;
+
+ /**
+ Client commands
+ */
+ String* _clientCommands;
+
+ /**
+ Client specific durations
+ */
+ Uint64* _clientDurations;
+
+ /**
+ Client specific delays
+ */
+ Uint64* _clientDelays;
+
+ /**
+ The total number of clients for this test
+ */
+ Uint32 _clientCount;
+
+ /**
+ current client name
+ */
+ String _currClient;
+
+ /**
+ current client count
+ */
+ Uint32 _currClientCount;
+
+ /**
+ Stress Controller Log file.
+ */
+ String _stressTestLogFile;
+
+ /**
+ StressTest Client PID file
+ */
+ String _stressTestClientPIDFile;
+
+ /**
+ StressTest Client Log file
+ */
+ String _stressTestClientLogFile;
+
+ /**
+ StressTest temporary Client PID file
+ */
+ String _tmpStressTestClientPIDFile;
+};
+
+PEGASUS_NAMESPACE_END
+
+#endif /* Pegasus_StressTestControllerCommand_h */
diff --git a/test/StressTestController/StressTestControllerException.cpp b/test/StressTestController/StressTestControllerException.cpp
new file mode 100644
index 0000000..2d1959a
--- /dev/null
+++ b/test/StressTestController/StressTestControllerException.cpp
@@ -0,0 +1,141 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: John Alex, IBM (johnalex@us.ibm.com)
+//
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Common/Exception.h>
+#include "StressTestControllerException.h"
+
+PEGASUS_NAMESPACE_BEGIN
+
+
+/**
+
+ Default exception identifier. This identifier is used if the specified
+ identifier is out of range. This identifier corresponds to a default
+ (generic) message in the array of exception message strings.
+
+ */
+const Uint32 StressTestControllerException::DEFAULT_ID = 0;
+
+/**
+
+ Minimum valid exception identifier.
+
+ */
+const Uint32 StressTestControllerException::MIN_ID = DEFAULT_ID;
+
+/**
+
+ Exception identifier indicating "Syntax Error" with client option.
+
+ */
+
+const Uint32 StressTestControllerException::INVALID_OPTION = 1;
+
+/**
+
+ Exception identifier indicating "Syntax Error" with client option operator.
+
+ */
+const Uint32 StressTestControllerException::INVALID_OPERATOR = 2;
+
+/**
+
+ Exception identifier indicating "Missing closing square brace".
+
+ */
+const Uint32 StressTestControllerException::MISSING_BRACE = 3;
+
+/**
+
+ Exception identifier indicating "Missing value for client option".
+
+ */
+const Uint32 StressTestControllerException::MISSING_VALUE = 4;
+
+/**
+
+ Maximum valid exception identifier. This value must be updated when
+ a new exception identifier and message are added.
+
+ */
+const Uint32 StressTestControllerException::MAX_ID =
+ StressTestControllerException::MISSING_VALUE;
+
+/**
+
+ Exception message strings. The exception identifier is used as an
+ index into this array to retrieve the appropriate exception message
+ string. When a new identifier is added, this array must be updated
+ appropriately.
+
+ */
+const char* StressTestControllerException::_messageStrings [] =
+{
+ "Error in TestStressTestController command: ",
+ "Syntax Error Client option name: ",
+ "Syntax Error Client option operator: ",
+ "Missing closing square brace: ",
+ "Missing value for client option: "
+};
+
+/**
+
+ Constructs a StressTestControllerException with a message corresponding to
+ the specified exception ID.
+
+ @param ID the integer exception identifier
+
+ */
+StressTestControllerException::StressTestControllerException (
+ Uint32 ID) : CommandException
+ (_messageStrings [(ID > MAX_ID) ? DEFAULT_ID : ID])
+{
+}
+
+/**
+
+ Constructs a StressTestControllerException with the specified message.
+
+ @param exceptionMessage a string containing the exception message
+
+ */
+StressTestControllerException::StressTestControllerException (
+ const String& exceptionMessage) : CommandException (exceptionMessage)
+{
+}
+
+PEGASUS_NAMESPACE_END
diff --git a/test/StressTestController/StressTestControllerException.h b/test/StressTestController/StressTestControllerException.h
new file mode 100644
index 0000000..d42fd7b
--- /dev/null
+++ b/test/StressTestController/StressTestControllerException.h
@@ -0,0 +1,145 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: John Alex, IBM (johnalex@us.ibm.com)
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#ifndef Pegasus_StressTestControllerException_h
+#define Pegasus_StressTestControllerException_h
+
+#include <Clients/cliutils/CommandException.h>
+
+
+PEGASUS_NAMESPACE_BEGIN
+
+/**
+
+ StressTestControllerException signals that an exception has occurred in
+ executing the StressTestController command.
+
+
+ */
+class StressTestControllerException : public CommandException
+{
+public:
+ /**
+
+ Constructs an StressTestControllerException with a message corresponding
+ to the specified exception ID.
+
+ @param ID the integer exception identifier
+
+ */
+ StressTestControllerException (Uint32 ID);
+
+
+ /**
+
+ Constructs an StressTestControllerException with the specified message.
+
+ @param exceptionMessage a string containing the exception message
+
+ */
+ StressTestControllerException (const String& exceptionMessage);
+
+ //
+ // Exception identifiers
+ //
+ // These are used to index into the messageStrings array to retrieve the
+ // appropriate exception message string. When a new identifier is added,
+ // the messageStrings array and MAX_ID must be updated appropriately.
+ //
+
+ /**
+
+ Default exception identifier. This identifier is used if the specified
+ identifier is out of range. This identifier corresponds to a default
+ (generic) message in the array of exception message strings.
+
+ */
+ static const Uint32 DEFAULT_ID;
+
+ /**
+
+ Minimum valid exception identifier.
+
+ */
+ static const Uint32 MIN_ID;
+
+ /**
+
+ Exception identifier indicating "Syntax Error" with client option.
+
+ */
+
+ static const Uint32 INVALID_OPTION;
+
+ /**
+
+ Exception identifier indicating "Syntax Error" with client option
+ operator.
+
+ */
+ static const Uint32 INVALID_OPERATOR;
+
+ /**
+
+ Exception identifier indicating "Missing closing square brace".
+
+ */
+ static const Uint32 MISSING_BRACE;
+
+ /**
+
+ Exception identifier indicating "Missing value for client option".
+
+ */
+ static const Uint32 MISSING_VALUE;
+
+
+ static const Uint32 MAX_ID;
+
+private:
+ /**
+
+ Exception message strings. The exception identifier is used as an
+ index into this array to retrieve the appropriate exception message
+ string. When a new identifier is added, this array must be updated
+ appropriately.
+
+ */
+ static const char* _messageStrings [];
+};
+
+PEGASUS_NAMESPACE_END
+
+#endif /* Pegasus_StressTestControllerException_h */
diff --git a/test/StressTestController/StressTestControllerMain.cpp b/test/StressTestController/StressTestControllerMain.cpp
new file mode 100644
index 0000000..648894d
--- /dev/null
+++ b/test/StressTestController/StressTestControllerMain.cpp
@@ -0,0 +1,429 @@
+//%2006////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation, The Open Group.
+// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; VERITAS Software Corporation; The Open Group.
+// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+// EMC Corporation; Symantec Corporation; The Open Group.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+//==============================================================================
+//
+// Author: John Alex
+//
+// Modified By:
+//
+//%/////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include <Pegasus/getoopt/getoopt.h>
+#include <Clients/cliutils/CommandException.h>
+#include "StressTestController.h"
+#include <Pegasus/Common/TimeValue.h>
+#include <Pegasus/Common/FileSystem.h>
+
+//#define DEBUG
+#include <time.h>
+
+//
+// For Windows
+//
+#ifdef PEGASUS_OS_TYPE_WINDOWS
+ // for DWORD etc.
+ #include <windows.h>
+ // getpid() and others
+ typedef DWORD pid_t;
+ #include <process.h>
+#elif !defined(PEGASUS_OS_OS400)
+ #include <unistd.h>
+#endif
+
+
+/**
+ Signal handler set up SIGALARM.
+*/
+static Boolean useDefaults = false;
+
+
+/**
+ Message resource name
+ */
+
+static const char REQUIRED_ARGS_MISSING [] =
+ "Required arguments missing.";
+static const char REQUIRED_ARGS_MISSING_KEY [] =
+ "Clients.cimuser.CIMUserCommand.REQUIRED_ARGS_MISSING";
+
+static const char ERR_OPTION_NOT_SUPPORTED [] =
+ "Invalid option. Use '--help' to obtain command syntax.";
+
+static const char ERR_OPTION_NOT_SUPPORTED_KEY[] =
+ "Clients.cimuser.CIMUserCommand..ERR_OPTION_NOT_SUPPORTED";
+
+static const char ERR_USAGE [] =
+ "Incorrect usage. Use '--help' to obtain command syntax.";
+
+static const char ERR_USAGE_KEY [] =
+ "Clients.cimuser.CIMUserCommand..ERR_USAGE";
+
+
+//
+// exclude main from the Pegasus Namespace
+//
+PEGASUS_USING_PEGASUS;
+PEGASUS_USING_STD;
+
+
+int main (int argc, char* argv [])
+{
+ char strTime[256];
+ struct tm tmTime;
+ int rc;
+ String fileName = String::EMPTY;
+ ofstream log_file;
+
+
+ tmTime = getCurrentActualTime();
+ strftime(strTime,256,"%d%m%Y%H%M%S.",&tmTime);
+
+ StressTestControllerCommand command=StressTestControllerCommand();
+
+ //
+ // Generate log files and PID files
+ //
+ if (!command.generateRequiredFileNames(strTime))
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME\
+ <<"::Failed to generate required files for tests. "<<endl;
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+
+ //
+ // open the log file
+ //
+ OpenAppend(log_file,command.getStressTestLogFile());
+
+ if (!log_file)
+ {
+ log_file.close();
+ cout<<"Cannot get file "<<command.getStressTestLogFile()<<endl;
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+ strftime(strTime,256,"%d/%m/%Y at %H:%M:%S\n",&tmTime);
+ log_file<<StressTestControllerCommand::COMMAND_NAME\
+ <<"::Initiated on "<<strTime<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME\
+ <<"::Process ID: "<<getpid()<<endl;
+
+ try
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME;
+ log_file<<"::Geting Command Options."<<endl;
+ if(verboseEnabled)
+ {
+ cout<<StressTestControllerCommand::COMMAND_NAME;
+ cout<<"::Getting Command options."<<endl;
+ }
+ //
+ // validate and set command arguments
+ //
+ command.setCommand (argc, argv);
+ }
+ catch (const CommandFormatException& cfe)
+ {
+ String msg(cfe.getMessage());
+
+ log_file<< StressTestControllerCommand::COMMAND_NAME << "::" \
+ << msg << endl;
+ cerr<< StressTestControllerCommand::COMMAND_NAME << "::"\
+ << msg << endl;
+
+ if (msg.find(String("Unknown flag")) != PEG_NOT_FOUND)
+ {
+
+ cerr<< StressTestControllerCommand::COMMAND_NAME <<
+ "::" << ERR_OPTION_NOT_SUPPORTED << endl;
+ log_file<< StressTestControllerCommand::COMMAND_NAME <<
+ "::" << ERR_OPTION_NOT_SUPPORTED << endl;
+ }
+ else
+ {
+ cerr<< StressTestControllerCommand::COMMAND_NAME <<
+ "::" << ERR_USAGE << endl;
+ log_file<< StressTestControllerCommand::COMMAND_NAME <<
+ "::" << ERR_USAGE << endl;
+ }
+
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+ catch (...)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Unknown exception caught when setting commands."<<endl;
+ cerr<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Unknown exception caught when setting commands."<<endl;
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+
+ //
+ // For help or version options execute usage/version and
+ // exit
+ //
+ if ((command.getOperationType() == OPERATION_TYPE_HELP)
+ ||(command.getOperationType() == OPERATION_TYPE_VERSION))
+ {
+ rc = command.execute (cout, cerr);
+ log_file.close();
+ //
+ // Log file not required when help or verbose is opted.
+ //
+ FileSystem::removeFile(command.getStressTestLogFile());
+ exit (rc);
+ }
+
+ String filename;
+
+ //
+ // If a configuration file is specified then:
+ // Check if it exists as indicated, if not
+ // also look for it in the default config dir.
+ //
+ if (command.IsConfigFilePathSpecified())
+ {
+ filename = command.getConfigFilePath();
+ FileSystem::translateSlashes(filename);
+ //
+ // Check whether the file exists or not
+ //
+ if (!FileSystem::exists(filename))
+ {
+ //
+ // Check for file in default directory as well
+ //
+ fileName = String::EMPTY;
+ fileName.append(StressTestControllerCommand::DEFAULT_CFGDIR);
+ fileName.append(filename);
+
+ if (!FileSystem::exists(fileName))
+ {
+ cerr << StressTestControllerCommand::COMMAND_NAME ;
+ cerr << "::Specified Configuration file \""<<filename;
+ cerr << "\" does not exist."<<endl;
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Using config file: "<<fileName<<endl;
+ }
+ else
+ {
+ fileName = filename;
+ }
+
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Using config file: "<<fileName<<endl;
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Using config file: "<<fileName<<endl;
+ }
+ else
+ {
+ //
+ // Use default file in default dir.
+ //
+ fileName = String::EMPTY;
+ fileName.append(StressTestControllerCommand::DEFAULT_CFGDIR);
+ fileName.append(StressTestControllerCommand::FILENAME);
+ //
+ // Use hard coded default configuration values if default conf. file
+ // was not found.
+ if (!FileSystem::exists(fileName))
+ {
+ //
+ // Use Hard-coded default values
+ //
+ useDefaults = true;
+ }
+ else
+ {
+ log_file << StressTestControllerCommand::COMMAND_NAME <<
+ "::Using default file: " << fileName<<endl;
+ cout << StressTestControllerCommand::COMMAND_NAME <<
+ "::Using default file: " << fileName<<endl;
+ }
+ }
+
+ //
+ // Read the contents of the file
+ //
+ try
+ {
+ //
+ // Use Hard-coded default values
+ //
+ if (useDefaults)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Using hard coded default config values."<<endl;
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Using hard coded default config values."<<endl;
+ command.getDefaultClients(log_file);
+ }
+ else
+ {
+ log_file << StressTestControllerCommand::COMMAND_NAME <<
+ "::Reading config file: " << fileName<<endl;
+ if (verboseEnabled)
+ {
+ cout<< StressTestControllerCommand::COMMAND_NAME <<
+ "::Reading config file: " << fileName<<endl;
+ }
+ command.getFileContent(fileName,log_file);
+ }
+ }
+ catch (NoSuchFile& e)
+ {
+ String msg(e.getMessage());
+
+ log_file << StressTestControllerCommand::COMMAND_NAME <<
+ ": " << msg << endl;
+ cerr << StressTestControllerCommand::COMMAND_NAME <<
+ ": " << msg << endl;
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+
+ }
+ catch (Exception& e )
+ {
+ String msg(e.getMessage());
+ log_file << StressTestControllerCommand::COMMAND_NAME <<
+ "::" << msg << endl;
+ cerr << StressTestControllerCommand::COMMAND_NAME <<
+ "::Invalid Configuration ";
+ cerr << "in File: " << fileName << endl;
+ cerr << msg << endl;
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+ catch (...)
+ {
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Unknown exception caught when acquiring configuration."<<endl;
+ cerr<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Unknown exception caught when acquiring configuration."<<endl;
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+
+ log_file << StressTestControllerCommand::COMMAND_NAME <<
+ "::Generating Client Commands"<< endl;
+ if(verboseEnabled)
+ {
+ cout << StressTestControllerCommand::COMMAND_NAME <<
+ "::Generating Client Commands"<< endl;
+ }
+
+ //
+ // TimeStamp
+ //
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Initiated on "<<strTime<<endl;
+ log_file<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Process ID: "<<getpid()<<endl;
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Initiated on "<<strTime<<endl;
+ cout<<StressTestControllerCommand::COMMAND_NAME<<
+ "::Process ID: "<<getpid()<<endl;
+
+ if(!command.generateClientCommands(log_file))
+ {
+ cerr << StressTestControllerCommand::COMMAND_NAME <<
+ "::Failed to Generate Client Commands."<< endl;
+ log_file << StressTestControllerCommand::COMMAND_NAME <<
+ "::Failed to Generate Client Commands."<< endl;
+ log_file.close();
+ command.removeUnusedFiles();
+ exit (Command::RC_ERROR);
+ }
+
+ //
+ // Getting current time
+ //
+ tmTime = getCurrentActualTime();
+ strftime(strTime,256,"%d/%m/%Y at %H:%M:%S\n",&tmTime);
+ log_file << StressTestControllerCommand::COMMAND_NAME <<endl;
+ log_file << " Preparing to execute Clients on "<<strTime<<endl;
+
+ //
+ // Begin to run stress Tests
+ //
+ rc = command.execute (cout, cerr);
+
+ //
+ // Getting current time after stress Tests are completed
+ //
+ tmTime = getCurrentActualTime();
+
+ strftime(strTime,256,"%d/%m/%Y at %H:%M:%S\n",&tmTime);
+
+ //
+ // Check overall status of tests
+ //
+ if(rc)
+ {
+ log_file << StressTestControllerCommand::COMMAND_NAME;
+ log_file << "::execution interrupted on "<<strTime<<endl;
+ cout << StressTestControllerCommand::COMMAND_NAME;
+ cout << "::execution interrupted on "<<strTime<<endl;
+ } else {
+ log_file << StressTestControllerCommand::COMMAND_NAME;
+ log_file << "::successfully completed on "<<strTime<<endl;
+ cout << StressTestControllerCommand::COMMAND_NAME;
+ cout << "::successfully completed on "<<strTime<<endl;
+ }
+ cout <<"IMPORTANT: ";
+ cout <<"Please check the Controller log file for additional info and the"
+ << endl;
+ cout <<" Client log file for individual errors which may or may "
+ <<"not have "<< endl;
+ cout <<" caused a stress test failure. "<< endl;
+ cout <<" Log Directory:"<<endl;
+ cout <<" "<<
+ FileSystem::extractFilePath(command.getStressTestLogFile())<<endl;
+ cout <<"\n Controller log: "<<
+ FileSystem::extractFileName(command.getStressTestLogFile())<<endl;
+ cout <<" Client log: "<<
+ FileSystem::extractFileName(command.getStressClientLogFile())<<endl;
+ log_file.close();
+ exit (rc);
+ return rc;
+} /* main */
diff --git a/test/StressTestController/default_stresstest.conf b/test/StressTestController/default_stresstest.conf
new file mode 100644
index 0000000..233cfe9
--- /dev/null
+++ b/test/StressTestController/default_stresstest.conf
@@ -0,0 +1,12 @@
+# Default Config File: default_stresstest.conf
+
+#Total Duration of Tests
+DURATION =180
+
+#Tolerance Level of tests in percentage(0% indicates, no tolerance for errors)
+ToleranceLevel=0
+
+#Clients
+ModelWalkStressClient=5
+WrapperStressClient=5
+[ClientName=CLI,options=" niall"]
diff --git a/test/StressTestController/tests/Makefile b/test/StressTestController/tests/Makefile
new file mode 100644
index 0000000..6f06bdf
--- /dev/null
+++ b/test/StressTestController/tests/Makefile
@@ -0,0 +1,117 @@
+#//%2006////////////////////////////////////////////////////////////////////////
+#//
+#// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
+#// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
+#// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation, The Open Group.
+#// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
+#// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; VERITAS Software Corporation; The Open Group.
+#// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
+#// EMC Corporation; Symantec Corporation; The Open Group.
+#//
+#// Permission is hereby granted, free of charge, to any person obtaining a copy
+#// of this software and associated documentation files (the "Software"), to
+#// deal in the Software without restriction, including without limitation the
+#// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+#// sell copies of the Software, and to permit persons to whom the Software is
+#// furnished to do so, subject to the following conditions:
+#//
+#// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
+#// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
+#// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+#// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+#// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+#// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+#// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#//
+#//==============================================================================
+ROOT = $(PEGASUS_ROOT)
+
+DIR = test/StressTestController/tests
+
+include $(ROOT)/mak/config.mak
+include $(ROOT)/mak/test.mak
+
+RESULTFILE = $(TMP_DIR)/result
+MASTERRESULTFILE = $(ROOT)/$(DIR)/result.master
+
+
+clean:
+ @$(RM) $(RESULTFILE)
+
+tests:
+ @$(RM) $(RESULTFILE)
+ @$(ECHO) Running Usage tests for: TestStressTestController
+ @$(MAKE) -i -s stresstests_ignoreerror
+ @$(STRIPCRS)
+ $(COMPARERESULTS)
+ @$(ECHO) +++ Usage Tests passed +++
+ @$(RM) $(RESULTFILE)
+
+stresstests_ignoreerror:
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -a >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -b >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -c >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -d >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -e >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -f >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -g >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -i >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -j >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -k >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -l >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -m >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -n >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -o >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -q >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -t >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -v >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -x >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -y >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage - error" >> $(RESULTFILE)
+ @TestStressTestController -z >> $(RESULTFILE) $(REDIRECTERROR)
+
+ @$(ECHO) "Missing required value for hostname - error" >> $(RESULTFILE)
+ @TestStressTestController -h >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Missing required value for port - error" >> $(RESULTFILE)
+ @TestStressTestController -p >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Missing required value for username - error" >> $(RESULTFILE)
+ @TestStressTestController -u >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Missing required value for password - error" >> $(RESULTFILE)
+ @TestStressTestController -w >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Display usage" >> $(RESULTFILE)
+ @TestStressTestController --help >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Missing configuration file - error" >> $(RESULTFILE)
+ @TestStressTestController nofile.conf >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Unexpected Argument - error" >> $(RESULTFILE)
+ @TestStressTestController nofile.conf anotherfile.conf>> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "Invalid Tolerance, Port number, & Host name - error" >> $(RESULTFILE)
+ @TestStressTestController invalid_configuration.conf >> $(RESULTFILE) $(REDIRECTERROR)
+ @$(ECHO) "No clients specified in Configuration - error" >> $(RESULTFILE)
+ @TestStressTestController invalid_noclients.conf>> $(RESULTFILE) $(REDIRECTERROR)
+
+poststarttests:
+
+depend:
diff --git a/test/StressTestController/tests/invalid_configuration.conf b/test/StressTestController/tests/invalid_configuration.conf
new file mode 100644
index 0000000..258bb44
--- /dev/null
+++ b/test/StressTestController/tests/invalid_configuration.conf
@@ -0,0 +1,6 @@
+Duration=1
+hostname=test
+WrapperStressClient=1
+ToleranceLevel=200
+Port=99999
+[hostname=testa,ClientName=CLI,options="ei pg_computersystem"]
diff --git a/test/StressTestController/tests/invalid_noclients.conf b/test/StressTestController/tests/invalid_noclients.conf
new file mode 100644
index 0000000..fa81ada
--- /dev/null
+++ b/test/StressTestController/tests/invalid_noclients.conf
@@ -0,0 +1 @@
+# empty file
diff --git a/test/StressTestController/tests/result.master b/test/StressTestController/tests/result.master
new file mode 100644
index 0000000..e6fb8c8
--- /dev/null
+++ b/test/StressTestController/tests/result.master
@@ -0,0 +1,109 @@
+Display usage - error
+TestStressTestController::Unknown flag -a
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -b
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -c
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -d
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -e
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -f
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -g
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -i
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -j
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -k
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -l
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -m
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -n
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -o
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -q
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -t
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -v
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -x
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -y
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Display usage - error
+TestStressTestController::Unknown flag -z
+TestStressTestController::Invalid option. Use '--help' to obtain command syntax.
+Missing required value for hostname - error
+TestStressTestController::Missing required value for flag h
+TestStressTestController::Incorrect usage. Use '--help' to obtain command syntax.
+Missing required value for port - error
+TestStressTestController::Missing required value for flag p
+TestStressTestController::Incorrect usage. Use '--help' to obtain command syntax.
+Missing required value for username - error
+TestStressTestController::Missing required value for flag u
+TestStressTestController::Incorrect usage. Use '--help' to obtain command syntax.
+Missing required value for password - error
+TestStressTestController::Missing required value for flag w
+TestStressTestController::Incorrect usage. Use '--help' to obtain command syntax.
+Display usage
+Usage: TestStressTestController [ -s ] [ -h hostname ] [ -p portnumber ]
+ [ -u username ] [ -w password ] [ --help ]
+ [ --version ] [ --verbose ] [<config_filename>]
+Options :
+ -h - Connect to CIM Server on specified hostname.
+ --help - Display this help message.
+ -p - Connect to CIM Server on specified portnumber.
+ -s - Use SSL protocol between Stress Test Client
+ and the CIM Server
+ -u - Connect to CIM Server using the specified username
+ --version - Display CIM Server version number
+ --verbose - Display verbose information
+ -w - Connect to CIM Server using the specified password
+
+Operands :
+ <config_filename>
+ - Specifies the name of the configuration file that is to be used
+ for the tests.
+
+Missing configuration file - error
+TestStressTestController::Specified Configuration file "nofile.conf" does not exist.
+Unexpected Argument - error
+TestStressTestController::argument "anotherfile.conf" was unexpected
+TestStressTestController::Incorrect usage. Use '--help' to obtain command syntax.
+Invalid Tolerance, Port number, & Host name - error
+TestStressTestController::Using config file: invalid_configuration.conf
+TestStressTestController::Invalid Configuration in File: invalid_configuration.conf
+
+ line#4:: Invalid Property Value: ToleranceLevel=200
+ line#5:: Invalid Property Value: port=99999
+ line#6:: Invalid Client property value: hostname=testa in [hostname=testa,ClientName=CLI,options="ei pg_computersystem"]
+No clients specified in Configuration - error
+TestStressTestController::Using config file: invalid_noclients.conf
+TestStressTestController::Invalid Configuration in File: invalid_noclients.conf
+
+ TestStressTestController::No clients found.