no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / xpcom / tests / TestHarness.h
blobe5754977466e6111166b94265b9d459580b8cbcc
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/. */
6 /*
7 * Test harness for XPCOM objects, providing a scoped XPCOM initializer,
8 * nsCOMPtr, nsRefPtr, do_CreateInstance, do_GetService, ns(Auto|C|)String,
9 * and stdio.h/stdlib.h.
12 #ifndef TestHarness_h__
13 #define TestHarness_h__
15 #include "mozilla/ArrayUtils.h"
16 #include "mozilla/Attributes.h"
18 #include "prenv.h"
19 #include "nsComponentManagerUtils.h"
20 #include "nsServiceManagerUtils.h"
21 #include "nsCOMPtr.h"
22 #include "nsString.h"
23 #include "nsAppDirectoryServiceDefs.h"
24 #include "nsDirectoryServiceDefs.h"
25 #include "nsDirectoryServiceUtils.h"
26 #include "nsIDirectoryService.h"
27 #include "nsIFile.h"
28 #include "nsIObserverService.h"
29 #include "nsXULAppAPI.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include "mozilla/AppShutdown.h"
35 static uint32_t gFailCount = 0;
37 /**
38 * Prints the given failure message and arguments using printf, prepending
39 * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
40 * appending "\n" to eliminate having to type it at each call site.
42 MOZ_FORMAT_PRINTF(1, 2) void fail(const char* msg, ...) {
43 va_list ap;
45 printf("TEST-UNEXPECTED-FAIL | ");
47 va_start(ap, msg);
48 vprintf(msg, ap);
49 va_end(ap);
51 putchar('\n');
52 ++gFailCount;
55 /**
56 * Prints the given success message and arguments using printf, prepending
57 * "TEST-PASS " for the benefit of the test harness and
58 * appending "\n" to eliminate having to type it at each call site.
60 MOZ_FORMAT_PRINTF(1, 2) void passed(const char* msg, ...) {
61 va_list ap;
63 printf("TEST-PASS | ");
65 va_start(ap, msg);
66 vprintf(msg, ap);
67 va_end(ap);
69 putchar('\n');
72 //-----------------------------------------------------------------------------
74 class ScopedXPCOM : public nsIDirectoryServiceProvider2 {
75 public:
76 NS_DECL_ISUPPORTS
78 explicit ScopedXPCOM(const char* testName,
79 nsIDirectoryServiceProvider* dirSvcProvider = nullptr)
80 : mDirSvcProvider(dirSvcProvider) {
81 mTestName = testName;
82 printf("Running %s tests...\n", mTestName);
84 mInitRv = NS_InitXPCOM(nullptr, nullptr, this);
85 if (NS_FAILED(mInitRv)) {
86 fail("NS_InitXPCOM returned failure code 0x%" PRIx32,
87 static_cast<uint32_t>(mInitRv));
88 return;
92 ~ScopedXPCOM() {
93 // If we created a profile directory, we need to remove it.
94 if (mProfD) {
95 mozilla::AppShutdown::AdvanceShutdownPhase(
96 mozilla::ShutdownPhase::AppShutdownNetTeardown);
97 mozilla::AppShutdown::AdvanceShutdownPhase(
98 mozilla::ShutdownPhase::AppShutdownTeardown);
99 mozilla::AppShutdown::AdvanceShutdownPhase(
100 mozilla::ShutdownPhase::AppShutdown);
101 mozilla::AppShutdown::AdvanceShutdownPhase(
102 mozilla::ShutdownPhase::AppShutdownQM);
103 mozilla::AppShutdown::AdvanceShutdownPhase(
104 mozilla::ShutdownPhase::AppShutdownTelemetry);
106 if (NS_FAILED(mProfD->Remove(true))) {
107 NS_WARNING("Problem removing profile directory");
110 mProfD = nullptr;
113 if (NS_SUCCEEDED(mInitRv)) {
114 nsresult rv = NS_ShutdownXPCOM(nullptr);
115 if (NS_FAILED(rv)) {
116 fail("XPCOM shutdown failed with code 0x%" PRIx32,
117 static_cast<uint32_t>(rv));
118 exit(1);
122 printf("Finished running %s tests.\n", mTestName);
125 bool failed() { return NS_FAILED(mInitRv); }
127 already_AddRefed<nsIFile> GetProfileDirectory() {
128 if (mProfD) {
129 nsCOMPtr<nsIFile> copy = mProfD;
130 return copy.forget();
133 // Create a unique temporary folder to use for this test.
134 // Note that runcppunittests.py will run tests with a temp
135 // directory as the cwd, so just put something under that.
136 nsCOMPtr<nsIFile> profD;
137 nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
138 getter_AddRefs(profD));
139 NS_ENSURE_SUCCESS(rv, nullptr);
141 rv = profD->Append(u"cpp-unit-profd"_ns);
142 NS_ENSURE_SUCCESS(rv, nullptr);
144 rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
145 NS_ENSURE_SUCCESS(rv, nullptr);
147 mProfD = profD;
148 return profD.forget();
151 already_AddRefed<nsIFile> GetGREDirectory() {
152 if (mGRED) {
153 nsCOMPtr<nsIFile> copy = mGRED;
154 return copy.forget();
157 char* env = PR_GetEnv("MOZ_XRE_DIR");
158 nsCOMPtr<nsIFile> greD;
159 if (env) {
160 NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false, getter_AddRefs(greD));
163 mGRED = greD;
164 return greD.forget();
167 already_AddRefed<nsIFile> GetGREBinDirectory() {
168 if (mGREBinD) {
169 nsCOMPtr<nsIFile> copy = mGREBinD;
170 return copy.forget();
173 nsCOMPtr<nsIFile> greD = GetGREDirectory();
174 if (!greD) {
175 return greD.forget();
177 greD->Clone(getter_AddRefs(mGREBinD));
179 #ifdef XP_MACOSX
180 nsAutoCString leafName;
181 mGREBinD->GetNativeLeafName(leafName);
182 if (leafName.EqualsLiteral("Resources")) {
183 mGREBinD->SetNativeLeafName("MacOS"_ns);
185 #endif
187 nsCOMPtr<nsIFile> copy = mGREBinD;
188 return copy.forget();
191 ////////////////////////////////////////////////////////////////////////////
192 //// nsIDirectoryServiceProvider
194 NS_IMETHOD GetFile(const char* aProperty, bool* _persistent,
195 nsIFile** _result) override {
196 // If we were supplied a directory service provider, ask it first.
197 if (mDirSvcProvider && NS_SUCCEEDED(mDirSvcProvider->GetFile(
198 aProperty, _persistent, _result))) {
199 return NS_OK;
202 // Otherwise, the test harness provides some directories automatically.
203 if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
204 0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
205 0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
206 nsCOMPtr<nsIFile> profD = GetProfileDirectory();
207 NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
209 nsCOMPtr<nsIFile> clone;
210 nsresult rv = profD->Clone(getter_AddRefs(clone));
211 NS_ENSURE_SUCCESS(rv, rv);
213 *_persistent = true;
214 clone.forget(_result);
215 return NS_OK;
216 } else if (0 == strcmp(aProperty, NS_GRE_DIR)) {
217 nsCOMPtr<nsIFile> greD = GetGREDirectory();
218 NS_ENSURE_TRUE(greD, NS_ERROR_FAILURE);
220 *_persistent = true;
221 greD.forget(_result);
222 return NS_OK;
223 } else if (0 == strcmp(aProperty, NS_GRE_BIN_DIR)) {
224 nsCOMPtr<nsIFile> greBinD = GetGREBinDirectory();
225 NS_ENSURE_TRUE(greBinD, NS_ERROR_FAILURE);
227 *_persistent = true;
228 greBinD.forget(_result);
229 return NS_OK;
232 return NS_ERROR_FAILURE;
235 ////////////////////////////////////////////////////////////////////////////
236 //// nsIDirectoryServiceProvider2
238 NS_IMETHOD GetFiles(const char* aProperty,
239 nsISimpleEnumerator** _enum) override {
240 // If we were supplied a directory service provider, ask it first.
241 nsCOMPtr<nsIDirectoryServiceProvider2> provider =
242 do_QueryInterface(mDirSvcProvider);
243 if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
244 return NS_OK;
247 return NS_ERROR_FAILURE;
250 private:
251 const char* mTestName;
252 nsresult mInitRv = NS_ERROR_NOT_INITIALIZED;
253 nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
254 nsCOMPtr<nsIFile> mProfD;
255 nsCOMPtr<nsIFile> mGRED;
256 nsCOMPtr<nsIFile> mGREBinD;
259 NS_IMPL_QUERY_INTERFACE(ScopedXPCOM, nsIDirectoryServiceProvider,
260 nsIDirectoryServiceProvider2)
262 NS_IMETHODIMP_(MozExternalRefCountType)
263 ScopedXPCOM::AddRef() { return 2; }
265 NS_IMETHODIMP_(MozExternalRefCountType)
266 ScopedXPCOM::Release() { return 1; }
268 #endif // TestHarness_h__