00001 //////////////////////////////////////////////////////////////////////////////// 00002 /// 00003 /// \file 00004 /// \author Gerald Fahrnholz 00005 /// 00006 /// \defgroup GrpEnvironment Using Environment 00007 /// @{ 00008 /// \ingroup GrpTestUtils 00009 /// \brief 00010 /// Class Environment allows easy access to path informations, system environment variables 00011 /// and command line arguments. 00012 /// 00013 /// \n This class allows to manage/access/change the informations as described in 00014 /// the following section. It is the task of the application itself to make use of 00015 /// this information in a suitable way corresponding to the application's purpose. 00016 /// The class Environment itself simply provides the information and makes no use of it. 00017 /// 00018 /// The following features are supported. 00019 /// - <b>Path of Executable (Runtime):</b>\n 00020 /// get the path of the currently running executable (full path or only drive) 00021 /// 00022 /// - <b>Path of Sources (Compile time):</b>\n 00023 /// get the path where the sources were compiled (you may need this path to access 00024 /// data/config files stored within the source directories): 00025 /// - full path or drive 00026 /// - cut off part of the source dir 00027 /// - explicitly set the complete directory path 00028 /// 00029 /// - <b>Path for output and reference files:</b>\n 00030 /// - get/set the directory to generate test output files (e.g. protocols) 00031 /// - get/set directory to read some reference files from (e.g. valid data to 00032 /// be compared during testing 00033 /// 00034 /// - <b>Command Line Parameters</b>\n 00035 /// Assumed syntax for command line params is "-optionName [optionValue]"\n 00036 /// arguments not matching this rule are simply ignored, e.g. "--option" 00037 /// (used by Boost.Test) is skipped when parsing the command line 00038 /// - get/set command line param as strings 00039 /// - get/set command line param as arbitrary (streamable) numeric types 00040 /// 00041 /// - <b>System Environment Variables</b>\n 00042 /// - get/set environment variable as string 00043 /// - get/set environment variable as arbitrary (streamable) numeric types 00044 /// 00045 /// - <b>Name of user and computer</b>\n 00046 /// 00047 /// - <b>General functions</b>\n 00048 /// - get textual <b>description for a system error code</b> 00049 /// - <b>start</b> an arbitrary <b>executable file</b> 00050 /// 00051 /// <b>\n Examples of Usage:</b>\n 00052 /// \code 00053 /// 00054 /// #include "TestToolBox\EnvironmentImpl.h" 00055 /// namespace TTB = TestToolBox; 00056 /// 00057 /// // define input path somewhere within source directories 00058 /// // Remark: at startup the source directory is the directory 00059 /// // where file environmentImpl.h is stored 00060 /// TTB::TheEnvironment()->CutSourceDirAfter("\\SW-Root\\"); 00061 /// std::string myInputFilePath = TTB::TheEnvironment()->GetSourceDir() 00062 /// + "MyInputFiles\\TestCaseA.input" 00063 /// 00064 /// // accessing command line 00065 /// if (TTB::TheEnvironment()->IsExistingCommandLineOption("-trace")) 00066 /// { 00067 /// ... 00068 /// } 00069 /// long numOfExecutions = TTB::TheEnvironment()->GetCommandLineOptionVal<long>("-numExecutions") 00070 /// 00071 /// // accessing environment variable 00072 /// bool produceDetailedOutput = TTB::TheEnvironment()->GetSystemEnvVariableVal<bool>("DetailedOutput"); 00073 /// 00074 /// // Display a textual description of a system error code as received via 00075 /// // return value or via GetLastError() 00076 /// if (!SomeSystemFunctionCall()) 00077 /// { 00078 /// DWORD errCode = ::GetLastError(); 00079 /// cout << "Function failed, reason: " 00080 /// << TTB::Environment::GetErrorDescription(errCode).c_str() << std::endl; 00081 /// 00082 /// // Start notepad to display some test results 00083 /// TTB::Environment::StartExeFile("notepad.exe","c:\tmp\MyTestResults.txt"); 00084 /// 00085 /// \endcode 00086 /// 00087 /// \sa Environment.h (File documentation) 00088 /// \sa TestToolBox::Environment (class documentation) 00089 /// \sa GrpTestEnvironment (unit test for class Environment) 00090 /// 00091 //////////////////////////////////////////////////////////////////////////////// 00092 00093 #pragma once 00094 00095 #include <string> 00096 #include <map> 00097 #include "TestToolBox\CommonSources\CommonDefinitions.h" 00098 00099 #ifdef USE_TEST_INSTANCE_DLL 00100 # include "TestToolBox\TestInstanceDll.h" 00101 #endif 00102 00103 //************************************************************************ 00104 00105 namespace TestToolBox 00106 { 00107 00108 00109 //************************************************************************ 00110 //************************************************************************ 00111 00112 00113 /// \brief Class allows easy access to path informations, system environment variables 00114 /// and command line arguments. 00115 /// For more info about usage see \ref GrpEnvironment. 00116 /// 00117 /// \nosubgrouping 00118 /// \sa Environment.h (File documentation) 00119 /// \sa GrpTestEnvironment (unit test for class Environment) 00120 /// \sa GrpEnvironment (Usage documentation) 00121 class Environment 00122 { 00123 public: 00124 00125 /// Mode describing the behaviour of a called function in case of error 00126 enum CallMode 00127 { 00128 CM_DEFAULT, ///< return default value in case of error 00129 CM_THROW ///< throw std::exception in case of error 00130 }; 00131 ///\cond do not document 00132 00133 // Constructor 00134 // All path variables will be initialized. 00135 Environment(); 00136 00137 // Destructor 00138 virtual ~Environment(); 00139 00140 // Get the only instance of TestEnv 00141 // Get the pointer to the only instance of this class 00142 #ifdef USE_TEST_INSTANCE_DLL 00143 static Environment* Get (void) 00144 {return TTB_GetInstance_Environment();} 00145 static Environment* s_pEnvironment; 00146 static void Cleanup (void) 00147 {TTB_CleanupInstance_Environment();} 00148 #else 00149 static Environment* Get (void) 00150 {if (!s_pEnvironment) s_pEnvironment = new Environment; 00151 return s_pEnvironment;} 00152 static Environment* s_pEnvironment; 00153 static void Cleanup (void) 00154 {delete s_pEnvironment; s_pEnvironment = 0;} 00155 #endif 00156 00157 ///\endcond 00158 00159 //--------------------------------------------------------------- 00160 /// \name Exe path 00161 /// \{ 00162 00163 /// Get complete path for exe file (e.g. "C:\MyTargetBin\MyAppname.exe") 00164 std::string GetExeFileFullPath (void) 00165 {return m_exeFileFullPath;} 00166 00167 /// Get directory path (e.g. "C:\MyTargetBin") 00168 std::string GetExeDir (void) 00169 {return m_exeDir;} 00170 00171 /// Get drive letter (e.g. "C:") 00172 std::string GetExeDrive (void) 00173 {return m_exeDrive;} 00174 00175 /// Get application name, i.e. name of executable without extension (e.g. "MyAppname") 00176 std::string GetAppName (void) 00177 {return m_appName;} 00178 00179 /// \} 00180 00181 //--------------------------------------------------------------- 00182 /// \name Source path 00183 /// \{ 00184 00185 00186 /// \brief Get the directory where the sources are stored. 00187 /// The initial value is generated from the preprocessor expression __FILE__ 00188 /// and relates to the directory where the sources have been compiled (usually 00189 /// within a version management system) 00190 /// An arbitrary string can be set using SetSourceDir(). To limit the path 00191 /// use function CutSourceDirAfter(). // 00192 std::string GetSourceDir() 00193 {return m_sourceDir;} 00194 00195 /// Get drive letter (e.g. "C:") 00196 std::string GetSourceDrive (void) 00197 {return m_sourceDrive;} 00198 00199 /// \brief Find first occurance of the given string within source dir and 00200 /// cut off the rest of the source dir string 00201 void CutSourceDirAfter (std::string const & in_findStr); 00202 00203 /// Explicitly replace the value of SourceDir with the given string 00204 void SetSourceDir (std::string const & in_sourceDir) 00205 {m_sourceDir = in_sourceDir; CalculateSourceDrive();} 00206 00207 /// \} 00208 00209 00210 //--------------------------------------------------------------- 00211 /// \name Out/Ref directories 00212 /// Get and set file paths used for unit testing. When starting up both path directories 00213 /// are initialized with the executable directory as available through GetExeDir(). 00214 /// \{ 00215 00216 std::string GetOutputDir() 00217 {return m_outputDir;} 00218 00219 void SetOutputDir (std::string in_outputDir) 00220 {m_outputDir = in_outputDir;} 00221 00222 std::string GetReferenceDir() 00223 {return m_referenceDir;} 00224 00225 void SetReferenceDir (std::string in_referenceDir) 00226 {m_referenceDir = in_referenceDir;} 00227 00228 /// \} 00229 00230 00231 //--------------------------------------------------------------- 00232 /// \name Name of user and computer 00233 /// \{ 00234 00235 /// Get name of computer 00236 static std::string GetNameOfComputer (void); 00237 00238 /// Get name of user which has logged in 00239 static std::string GetNameOfUser (void); 00240 /// \} 00241 00242 //--------------------------------------------------------------- 00243 /// \name Access to command line 00244 /// When starting up all command line params of format "-option [value]" 00245 /// are read into an internal string map upon which all functions except 00246 /// GetCommandLineStr()/GetArgsStr() are working. 00247 /// \{ 00248 00249 /// Get the complete command line as a single string 00250 static std::string GetCommandLineStr (void); 00251 00252 /// Get the complete command line args as a single string. 00253 /// The name of the executable (usually arg0) is not contained. 00254 static std::string GetArgsStr (void); 00255 00256 /// Check whether the given option is given within the command line 00257 bool IsExistingCommandLineOption ( 00258 std::string const & in_nameOption) const 00259 {return m_cmdLineOptions.find(in_nameOption)!=m_cmdLineOptions.end();} 00260 00261 /// Get the given option in string format 00262 std::string GetCommandLineOption ( 00263 std::string const & in_nameOption); 00264 00265 /// Change/create the given option in string format 00266 void SetCommandLineOption ( 00267 std::string const & in_nameOption, 00268 std::string const & in_optionValue) 00269 {m_cmdLineOptions[in_nameOption]=in_optionValue;} 00270 00271 /// Get the given option in numeric/any streamable format 00272 template<class T> 00273 T GetCommandLineOptionVal( 00274 const std::string& in_nameOption, 00275 CallMode in_callMode = CM_DEFAULT) 00276 { 00277 TRCF("Environment::GetCommandLineOptionVal"); 00278 00279 std::string optionValAsString = GetCommandLineOption(in_nameOption); 00280 std::istringstream iss(optionValAsString); 00281 T result = T(); 00282 if ((iss >> result).fail()) 00283 { 00284 result = T(); // reset to default value 00285 std::ostringstream oss; 00286 oss << "Could not convert command line option >" << in_nameOption 00287 << "< with value >" << optionValAsString << "<" 00288 << " to type >" << typeid(T).name() << "<"; 00289 TRC(TL_ERROR, "ERROR: %s", oss.str().c_str()); 00290 if (in_callMode == CM_THROW) 00291 { 00292 TRC(TL_ERROR, "ERROR: throwing exception: %s", oss.str().c_str()); 00293 throw std::exception(oss.str().c_str()); 00294 } 00295 } 00296 return result; 00297 } 00298 00299 /// Set the given option in numeric/any streamable format 00300 template<class T> 00301 void SetCommandLineOptionVal( 00302 const std::string& in_nameOption, 00303 T in_val) 00304 { 00305 TRCF("Environment::SetCommandLineOptionVal"); 00306 00307 TRC(TL_DEBUG,"called for type %s", typeid(T).name()); 00308 00309 std::ostringstream oss; 00310 oss << in_val; 00311 SetCommandLineOption (in_nameOption,oss.str()); 00312 } 00313 /// \} 00314 00315 00316 //--------------------------------------------------------------- 00317 /// \name Access to system environment variables 00318 /// \{ 00319 00320 /// Check whether the given environment variable is existing 00321 bool IsExistingSystemEnvVariable ( 00322 std::string const & in_envVarName) 00323 {std::string dummy; return GetSystemEnvVariable(in_envVarName, dummy);} 00324 00325 /// \brief Get the given environment variable in string format 00326 /// A return value of false signals that the environment variable 00327 /// is not set. 00328 bool GetSystemEnvVariable ( 00329 std::string const & in_envVarName, 00330 std::string& out_envVarValue); 00331 00332 /// \brief Get the given environment variable as string. If variable is 00333 /// not existing an empty string is returned 00334 std::string GetSystemEnvVariable (std::string const & in_envVarName); 00335 00336 /// Set the given environment variable in string format 00337 void SetSystemEnvVariable ( 00338 std::string const & in_envVarName, 00339 std::string const & in_envVarValue); 00340 00341 /// Get the given environment variable in numeric/any streamable format 00342 template<class T> 00343 T GetSystemEnvVariableVal( 00344 const std::string& in_envVarName, 00345 CallMode in_callMode = CM_DEFAULT) 00346 { 00347 TRCF("Environment::GetSystemEnvVariableVal"); 00348 00349 std::string envVarValAsString = GetSystemEnvVariable(in_envVarName); 00350 std::istringstream iss(envVarValAsString); 00351 T result = T(); 00352 if ((iss >> result).fail()) 00353 { 00354 result = T(); // reset to default value 00355 std::ostringstream oss; 00356 oss << "Could not convert environment variable >" << in_envVarName 00357 << "< with value >" << envVarValAsString << "<" 00358 << " to type >" << typeid(T).name() << "<"; 00359 TRC(TL_ERROR, "ERROR: %s", oss.str().c_str()); 00360 if (in_callMode == CM_THROW) 00361 { 00362 TRC(TL_ERROR, "ERROR: throwing exception: %s", oss.str().c_str()); 00363 throw std::exception(oss.str().c_str()); 00364 } 00365 } 00366 return result; 00367 } 00368 00369 /// Set the given environment variable in numeric/any streamable format 00370 template<class T> 00371 void SetSystemEnvVariableVal( 00372 const std::string& in_envVarName, 00373 T in_val) 00374 { 00375 TRCF("Environment::SetSystemEnvVariableVal"); 00376 00377 TRC(TL_DEBUG,"called for type %s", typeid(T).name()); 00378 00379 std::ostringstream oss; 00380 oss << in_val; 00381 SetSystemEnvVariable (in_envVarName,oss.str()); 00382 } 00383 /// \} 00384 00385 //--------------------------------------------------------------- 00386 /// \name General Helper Functions 00387 /// \{ 00388 00389 /// Get a textual description for a system error code 00390 static std::string GetErrorDescription (int in_systemError); 00391 00392 /// Start an arbitrary executable file 00393 static bool StartExeFile ( 00394 std::string const & in_executableToStart, 00395 std::string const & in_startArguments =""); 00396 /// \} 00397 00398 protected: 00399 ///\cond do not document 00400 00401 // File/dir info about running executable 00402 std::string m_exeFileFullPath; 00403 std::string m_exeDir; 00404 std::string m_exeDrive; 00405 std::string m_appName; 00406 00407 // Dir info about source directory 00408 std::string m_sourceDir; 00409 std::string m_sourceDrive; 00410 00411 // Directory to generate output files (protocol files, reports, ...) 00412 std::string m_outputDir; 00413 00414 // Directory to read reference files from 00415 std::string m_referenceDir; 00416 ///\endcond 00417 00418 /// \brief Set of command options as read from command line\n 00419 /// each command option has the format -optionName [paramValue] 00420 typedef std::map<std::string,std::string> CmdLineOptions; 00421 00422 /// Stored command line options 00423 CmdLineOptions m_cmdLineOptions; 00424 00425 private: 00426 ///\cond do not document 00427 void CalculateSourceDrive (void); 00428 void ParseCommandLine (void); 00429 bool GetNextOption ( 00430 std::string& inOut_rCmdLine, 00431 std::string& out_rOpt, 00432 std::string& out_rPar); 00433 bool GetNextToken ( 00434 std::string& inOut_rCmdLine, 00435 std::string& out_token, 00436 std::string::size_type& out_tokenEndPos); 00437 ///\endcond 00438 00439 }; // class Environment 00440 00441 ///\cond do not document 00442 __declspec(selectany) Environment* Environment::s_pEnvironment = 0; 00443 ///\endcond 00444 00445 /// Access/create the singleton instance of Environment 00446 inline Environment* TheEnvironment (void) 00447 {return Environment::Get();} 00448 00449 //************************************************************************ 00450 //************************************************************************ 00451 00452 00453 } // namespace TestToolBox 00454 00455 ///@} // end group GrpEnvironment 00456