TestHarness.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * Test harness for XPCOM objects, providing a scoped XPCOM initializer,
  7. * nsCOMPtr, nsRefPtr, do_CreateInstance, do_GetService, ns(Auto|C|)String,
  8. * and stdio.h/stdlib.h.
  9. */
  10. #ifndef TestHarness_h__
  11. #define TestHarness_h__
  12. #include "mozilla/ArrayUtils.h"
  13. #include "prenv.h"
  14. #include "nsComponentManagerUtils.h"
  15. #include "nsServiceManagerUtils.h"
  16. #include "nsCOMPtr.h"
  17. #include "nsAutoPtr.h"
  18. #include "nsStringGlue.h"
  19. #include "nsAppDirectoryServiceDefs.h"
  20. #include "nsDirectoryServiceDefs.h"
  21. #include "nsDirectoryServiceUtils.h"
  22. #include "nsIDirectoryService.h"
  23. #include "nsIFile.h"
  24. #include "nsIProperties.h"
  25. #include "nsIObserverService.h"
  26. #include "nsXULAppAPI.h"
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <stdarg.h>
  30. static uint32_t gFailCount = 0;
  31. /**
  32. * Prints the given failure message and arguments using printf, prepending
  33. * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
  34. * appending "\n" to eliminate having to type it at each call site.
  35. */
  36. void fail(const char* msg, ...)
  37. {
  38. va_list ap;
  39. printf("TEST-UNEXPECTED-FAIL | ");
  40. va_start(ap, msg);
  41. vprintf(msg, ap);
  42. va_end(ap);
  43. putchar('\n');
  44. ++gFailCount;
  45. }
  46. /**
  47. * Prints the given success message and arguments using printf, prepending
  48. * "TEST-PASS " for the benefit of the test harness and
  49. * appending "\n" to eliminate having to type it at each call site.
  50. */
  51. void passed(const char* msg, ...)
  52. {
  53. va_list ap;
  54. printf("TEST-PASS | ");
  55. va_start(ap, msg);
  56. vprintf(msg, ap);
  57. va_end(ap);
  58. putchar('\n');
  59. }
  60. //-----------------------------------------------------------------------------
  61. class ScopedXPCOM : public nsIDirectoryServiceProvider2
  62. {
  63. public:
  64. NS_DECL_ISUPPORTS
  65. explicit ScopedXPCOM(const char* testName,
  66. nsIDirectoryServiceProvider *dirSvcProvider = nullptr)
  67. : mDirSvcProvider(dirSvcProvider)
  68. {
  69. mTestName = testName;
  70. printf("Running %s tests...\n", mTestName);
  71. nsresult rv = NS_InitXPCOM2(&mServMgr, nullptr, this);
  72. if (NS_FAILED(rv))
  73. {
  74. fail("NS_InitXPCOM2 returned failure code 0x%x", rv);
  75. mServMgr = nullptr;
  76. return;
  77. }
  78. }
  79. ~ScopedXPCOM()
  80. {
  81. // If we created a profile directory, we need to remove it.
  82. if (mProfD) {
  83. nsCOMPtr<nsIObserverService> os =
  84. do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
  85. MOZ_RELEASE_ASSERT(os);
  86. MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-net-teardown", nullptr));
  87. MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-teardown", nullptr));
  88. MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change", nullptr));
  89. MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-qm", nullptr));
  90. MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-telemetry", nullptr));
  91. if (NS_FAILED(mProfD->Remove(true))) {
  92. NS_WARNING("Problem removing profile directory");
  93. }
  94. mProfD = nullptr;
  95. }
  96. if (mServMgr)
  97. {
  98. NS_RELEASE(mServMgr);
  99. nsresult rv = NS_ShutdownXPCOM(nullptr);
  100. if (NS_FAILED(rv))
  101. {
  102. fail("XPCOM shutdown failed with code 0x%x", rv);
  103. exit(1);
  104. }
  105. }
  106. printf("Finished running %s tests.\n", mTestName);
  107. }
  108. bool failed()
  109. {
  110. return mServMgr == nullptr;
  111. }
  112. already_AddRefed<nsIFile> GetProfileDirectory()
  113. {
  114. if (mProfD) {
  115. nsCOMPtr<nsIFile> copy = mProfD;
  116. return copy.forget();
  117. }
  118. // Create a unique temporary folder to use for this test.
  119. // Note that runcppunittests.py will run tests with a temp
  120. // directory as the cwd, so just put something under that.
  121. nsCOMPtr<nsIFile> profD;
  122. nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
  123. getter_AddRefs(profD));
  124. NS_ENSURE_SUCCESS(rv, nullptr);
  125. rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
  126. NS_ENSURE_SUCCESS(rv, nullptr);
  127. rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
  128. NS_ENSURE_SUCCESS(rv, nullptr);
  129. mProfD = profD;
  130. return profD.forget();
  131. }
  132. already_AddRefed<nsIFile> GetGREDirectory()
  133. {
  134. if (mGRED) {
  135. nsCOMPtr<nsIFile> copy = mGRED;
  136. return copy.forget();
  137. }
  138. char* env = PR_GetEnv("MOZ_XRE_DIR");
  139. nsCOMPtr<nsIFile> greD;
  140. if (env) {
  141. NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false,
  142. getter_AddRefs(greD));
  143. }
  144. mGRED = greD;
  145. return greD.forget();
  146. }
  147. already_AddRefed<nsIFile> GetGREBinDirectory()
  148. {
  149. if (mGREBinD) {
  150. nsCOMPtr<nsIFile> copy = mGREBinD;
  151. return copy.forget();
  152. }
  153. nsCOMPtr<nsIFile> greD = GetGREDirectory();
  154. if (!greD) {
  155. return greD.forget();
  156. }
  157. greD->Clone(getter_AddRefs(mGREBinD));
  158. #ifdef XP_MACOSX
  159. nsAutoCString leafName;
  160. mGREBinD->GetNativeLeafName(leafName);
  161. if (leafName.Equals("Resources")) {
  162. mGREBinD->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
  163. }
  164. #endif
  165. nsCOMPtr<nsIFile> copy = mGREBinD;
  166. return copy.forget();
  167. }
  168. ////////////////////////////////////////////////////////////////////////////
  169. //// nsIDirectoryServiceProvider
  170. NS_IMETHOD GetFile(const char *aProperty, bool *_persistent,
  171. nsIFile **_result) override
  172. {
  173. // If we were supplied a directory service provider, ask it first.
  174. if (mDirSvcProvider &&
  175. NS_SUCCEEDED(mDirSvcProvider->GetFile(aProperty, _persistent,
  176. _result))) {
  177. return NS_OK;
  178. }
  179. // Otherwise, the test harness provides some directories automatically.
  180. if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
  181. 0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
  182. 0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
  183. nsCOMPtr<nsIFile> profD = GetProfileDirectory();
  184. NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
  185. nsCOMPtr<nsIFile> clone;
  186. nsresult rv = profD->Clone(getter_AddRefs(clone));
  187. NS_ENSURE_SUCCESS(rv, rv);
  188. *_persistent = true;
  189. clone.forget(_result);
  190. return NS_OK;
  191. } else if (0 == strcmp(aProperty, NS_GRE_DIR)) {
  192. nsCOMPtr<nsIFile> greD = GetGREDirectory();
  193. NS_ENSURE_TRUE(greD, NS_ERROR_FAILURE);
  194. *_persistent = true;
  195. greD.forget(_result);
  196. return NS_OK;
  197. } else if (0 == strcmp(aProperty, NS_GRE_BIN_DIR)) {
  198. nsCOMPtr<nsIFile> greBinD = GetGREBinDirectory();
  199. NS_ENSURE_TRUE(greBinD, NS_ERROR_FAILURE);
  200. *_persistent = true;
  201. greBinD.forget(_result);
  202. return NS_OK;
  203. }
  204. return NS_ERROR_FAILURE;
  205. }
  206. ////////////////////////////////////////////////////////////////////////////
  207. //// nsIDirectoryServiceProvider2
  208. NS_IMETHOD GetFiles(const char *aProperty, nsISimpleEnumerator **_enum) override
  209. {
  210. // If we were supplied a directory service provider, ask it first.
  211. nsCOMPtr<nsIDirectoryServiceProvider2> provider =
  212. do_QueryInterface(mDirSvcProvider);
  213. if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
  214. return NS_OK;
  215. }
  216. return NS_ERROR_FAILURE;
  217. }
  218. private:
  219. const char* mTestName;
  220. nsIServiceManager* mServMgr;
  221. nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
  222. nsCOMPtr<nsIFile> mProfD;
  223. nsCOMPtr<nsIFile> mGRED;
  224. nsCOMPtr<nsIFile> mGREBinD;
  225. };
  226. NS_IMPL_QUERY_INTERFACE(
  227. ScopedXPCOM,
  228. nsIDirectoryServiceProvider,
  229. nsIDirectoryServiceProvider2
  230. )
  231. NS_IMETHODIMP_(MozExternalRefCountType)
  232. ScopedXPCOM::AddRef()
  233. {
  234. return 2;
  235. }
  236. NS_IMETHODIMP_(MozExternalRefCountType)
  237. ScopedXPCOM::Release()
  238. {
  239. return 1;
  240. }
  241. #endif // TestHarness_h__