unittests.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifdef _USE_CPPUNIT
  14. #include "unittests.hpp"
  15. #include "jstats.h"
  16. #include "jregexp.hpp"
  17. #include "jfile.hpp"
  18. /*
  19. * This is the main unittest driver for HPCC. From here,
  20. * all unit tests, be they internal or external (API),
  21. * will run.
  22. *
  23. * All internal unit tests, written on the same source
  24. * files as the implementation they're testing, can be
  25. * dynamically linked via the helper class below.
  26. *
  27. * All external unit tests (API tests, test-driven
  28. * development, interface documentation and general
  29. * usability tests) should be implemented as source
  30. * files within the same directory as this file, and
  31. * statically linked together.
  32. *
  33. * CPPUnit will automatically recognise and run them all.
  34. */
  35. void usage()
  36. {
  37. printf("\n"
  38. "Usage:\n"
  39. " unittests <options> <testnames>\n"
  40. "\n"
  41. "Options:\n"
  42. " -a --all Include all tests, including timing and stress tests\n"
  43. " -d --load path Dynamically load a library/all libraries in a directory.\n"
  44. " By default, the HPCCSystems lib directory is loaded.\n"
  45. " -e --exact Match subsequent test names exactly\n"
  46. " -h --help Display this help text\n"
  47. " -l --list List matching tests but do not execute them\n"
  48. " -x --exclude Exclude subsequent test names\n"
  49. "\n");
  50. }
  51. bool matchName(const char *name, const StringArray &patterns)
  52. {
  53. ForEachItemIn(idx, patterns)
  54. {
  55. bool match;
  56. const char *pattern = patterns.item(idx);
  57. if (strchr(pattern, '*'))
  58. {
  59. match = WildMatch(name, pattern, true);
  60. }
  61. else
  62. match = streq(name, pattern);
  63. if (match)
  64. return true;
  65. }
  66. return false;
  67. }
  68. LoadedObject *loadDll(const char *thisDll)
  69. {
  70. try
  71. {
  72. DBGLOG("Loading %s", thisDll);
  73. return new LoadedObject(thisDll);
  74. }
  75. catch (IException *E)
  76. {
  77. E->Release();
  78. }
  79. catch (...)
  80. {
  81. }
  82. return NULL;
  83. }
  84. void loadDlls(IArray &objects, const char * libDirectory)
  85. {
  86. const char * mask = "*" SharedObjectExtension;
  87. Owned<IFile> libDir = createIFile(libDirectory);
  88. Owned<IDirectoryIterator> libFiles = libDir->directoryFiles(mask,false,false);
  89. ForEach(*libFiles)
  90. {
  91. const char *thisDll = libFiles->query().queryFilename();
  92. if (!strstr(thisDll, "javaembed")) // Bit of a hack, but loading this if java not present terminates...
  93. {
  94. LoadedObject *loaded = loadDll(thisDll);
  95. if (loaded)
  96. objects.append(*loaded);
  97. }
  98. }
  99. }
  100. int main(int argc, char* argv[])
  101. {
  102. InitModuleObjects();
  103. StringArray includeNames;
  104. StringArray excludeNames;
  105. StringArray loadLocations;
  106. bool wildMatch = true;
  107. bool exclude = false;
  108. bool includeAll = false;
  109. bool verbose = false;
  110. bool list = false;
  111. bool useDefaultLocations = true;
  112. for (int argNo = 1; argNo < argc; argNo++)
  113. {
  114. const char *arg = argv[argNo];
  115. if (arg[0]=='-')
  116. {
  117. if (streq(arg, "-x") || streq(arg, "--exclude"))
  118. exclude = true;
  119. else if (streq(arg, "-v") || streq(arg, "--verbose"))
  120. verbose = true;
  121. else if (streq(arg, "-e") || streq(arg, "--exact"))
  122. wildMatch = false;
  123. else if (streq(arg, "-a") || streq(arg, "--all"))
  124. includeAll = true;
  125. else if (streq(arg, "-l") || streq(arg, "--list"))
  126. list = true;
  127. else if (streq(arg, "-d") || streq(arg, "--load"))
  128. {
  129. useDefaultLocations = false;
  130. argNo++;
  131. if (argNo<argc)
  132. loadLocations.append(argv[argNo]);
  133. }
  134. else
  135. {
  136. usage();
  137. exit(streq(arg, "-h") || streq(arg, "--help")?0:4);
  138. }
  139. }
  140. else
  141. {
  142. VStringBuffer pattern("*%s*", arg);
  143. if (wildMatch && !strchr(arg, '*'))
  144. arg = pattern.str();
  145. if (exclude)
  146. excludeNames.append(arg);
  147. else
  148. includeNames.append(arg);
  149. }
  150. }
  151. if (verbose)
  152. queryStderrLogMsgHandler()->setMessageFields(MSGFIELD_time);
  153. else
  154. removeLog();
  155. if (!includeNames.length())
  156. includeNames.append("*");
  157. if (!includeAll)
  158. {
  159. excludeNames.append("*stress*");
  160. excludeNames.append("*timing*");
  161. }
  162. if (useDefaultLocations)
  163. {
  164. // Default library location depends on the executable location...
  165. StringBuffer dir;
  166. splitFilename(argv[0], &dir, &dir, NULL, NULL);
  167. dir.replaceString(PATHSEPSTR "bin" PATHSEPSTR, PATHSEPSTR "lib" PATHSEPSTR);
  168. if (verbose)
  169. DBGLOG("Adding default library location %s", dir.str());
  170. loadLocations.append(dir);
  171. #ifdef _DEBUG
  172. dir.replaceString(PATHSEPSTR "lib" PATHSEPSTR, PATHSEPSTR "libs" PATHSEPSTR);
  173. loadLocations.append(dir);
  174. if (verbose)
  175. DBGLOG("Adding default library location %s", dir.str());
  176. #endif
  177. }
  178. IArray objects;
  179. ForEachItemIn(idx, loadLocations)
  180. {
  181. const char *location = loadLocations.item(idx);
  182. Owned<IFile> file = createIFile(location);
  183. switch (file->isDirectory())
  184. {
  185. case notFound:
  186. if (verbose && !useDefaultLocations)
  187. DBGLOG("Specified library location %s not found", location);
  188. break;
  189. case foundYes:
  190. loadDlls(objects, location);
  191. break;
  192. case foundNo:
  193. LoadedObject *loaded = loadDll(location);
  194. if (loaded)
  195. objects.append(*loaded);
  196. break;
  197. }
  198. }
  199. bool wasSuccessful = false;
  200. {
  201. // New scope as we need the TestRunner to be destroyed before unloading the dlls...
  202. CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
  203. CppUnit::TextUi::TestRunner runner;
  204. CppUnit::Test *all = registry.makeTest();
  205. int numTests = all->getChildTestCount();
  206. for (int i = 0; i < numTests; i++)
  207. {
  208. CppUnit::Test *sub = all->getChildTestAt(i);
  209. std::string name = sub->getName();
  210. if (matchName(name.c_str(), includeNames))
  211. {
  212. if (matchName(name.c_str(), excludeNames))
  213. {
  214. if (verbose)
  215. DBGLOG("Excluding test %s", name.c_str());
  216. }
  217. else if (list)
  218. printf("%s\n", name.c_str());
  219. else
  220. {
  221. if (verbose)
  222. DBGLOG("Including test %s", name.c_str());
  223. runner.addTest(sub);
  224. }
  225. }
  226. }
  227. wasSuccessful = list || runner.run( "", false );
  228. }
  229. objects.kill();
  230. ExitModuleObjects();
  231. releaseAtoms();
  232. return wasSuccessful;
  233. }
  234. //MORE: This can't be included in jlib because of the dll dependency
  235. class InternalStatisticsTest : public CppUnit::TestFixture
  236. {
  237. CPPUNIT_TEST_SUITE( InternalStatisticsTest );
  238. CPPUNIT_TEST(testMappings);
  239. CPPUNIT_TEST_SUITE_END();
  240. void testMappings()
  241. {
  242. try
  243. {
  244. verifyStatisticFunctions();
  245. }
  246. catch (IException * e)
  247. {
  248. StringBuffer msg;
  249. fprintf(stderr, "Failure: %s", e->errorMessage(msg).str());
  250. e->Release();
  251. ASSERT(false);
  252. }
  253. }
  254. };
  255. CPPUNIT_TEST_SUITE_REGISTRATION( InternalStatisticsTest );
  256. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( InternalStatisticsTest, "StatisticsTest" );
  257. #endif // _USE_CPPUNIT