1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Jeff Walden <jwalden+code@mit.edu>.
19 : * Portions created by the Initial Developer are Copyright (C) 2007
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /*
39 : * Test harness for XPCOM objects, providing a scoped XPCOM initializer,
40 : * nsCOMPtr, nsRefPtr, do_CreateInstance, do_GetService, ns(Auto|C|)String,
41 : * and stdio.h/stdlib.h.
42 : */
43 :
44 : #ifndef TestHarness_h__
45 : #define TestHarness_h__
46 :
47 : #if defined(_MSC_VER) && defined(MOZ_STATIC_JS)
48 : /*
49 : * Including jsdbgapi.h may cause build break with --disable-shared-js
50 : * This is a workaround for bug 673616.
51 : */
52 : #define STATIC_JS_API
53 : #endif
54 :
55 : #include "mozilla/Util.h"
56 :
57 : #include "nsComponentManagerUtils.h"
58 : #include "nsServiceManagerUtils.h"
59 : #include "nsCOMPtr.h"
60 : #include "nsAutoPtr.h"
61 : #include "nsStringGlue.h"
62 : #include "nsAppDirectoryServiceDefs.h"
63 : #include "nsDirectoryServiceDefs.h"
64 : #include "nsDirectoryServiceUtils.h"
65 : #include "nsIDirectoryService.h"
66 : #include "nsIFile.h"
67 : #include "nsIProperties.h"
68 : #include "nsIObserverService.h"
69 : #include "nsXULAppAPI.h"
70 : #include "jsdbgapi.h"
71 : #include <stdio.h>
72 : #include <stdlib.h>
73 : #include <stdarg.h>
74 :
75 : static PRUint32 gFailCount = 0;
76 :
77 : /**
78 : * Prints the given failure message and arguments using printf, prepending
79 : * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
80 : * appending "\n" to eliminate having to type it at each call site.
81 : */
82 0 : void fail(const char* msg, ...)
83 : {
84 : va_list ap;
85 :
86 0 : printf("TEST-UNEXPECTED-FAIL | ");
87 :
88 0 : va_start(ap, msg);
89 0 : vprintf(msg, ap);
90 0 : va_end(ap);
91 :
92 0 : putchar('\n');
93 0 : ++gFailCount;
94 0 : }
95 :
96 : /**
97 : * Prints the given success message and arguments using printf, prepending
98 : * "TEST-PASS " for the benefit of the test harness and
99 : * appending "\n" to eliminate having to type it at each call site.
100 : */
101 178 : void passed(const char* msg, ...)
102 : {
103 : va_list ap;
104 :
105 178 : printf("TEST-PASS | ");
106 :
107 178 : va_start(ap, msg);
108 178 : vprintf(msg, ap);
109 178 : va_end(ap);
110 :
111 178 : putchar('\n');
112 178 : }
113 :
114 : //-----------------------------------------------------------------------------
115 : // Code profiling
116 : //
117 : static const char* gCurrentProfile;
118 :
119 : /**
120 : * If the build has been configured properly, start the best code profiler
121 : * available on this platform.
122 : *
123 : * This is NOT thread safe.
124 : *
125 : * @precondition Profiling is not started
126 : * @param profileName A descriptive name for this profiling run. Every
127 : * attempt is made to name the profile data according
128 : * to this name, but check your platform's profiler
129 : * documentation for what this means.
130 : * @return true if profiling was available and successfully started.
131 : * @see StopProfiling
132 : */
133 : inline bool
134 : StartProfiling(const char* profileName)
135 : {
136 : NS_ASSERTION(profileName, "need a name for this profile");
137 : NS_PRECONDITION(!gCurrentProfile, "started a new profile before stopping another");
138 :
139 : JSBool ok = JS_StartProfiling(profileName);
140 : gCurrentProfile = profileName;
141 : return ok ? true : false;
142 : }
143 :
144 : /**
145 : * Stop the platform's profiler. For what this means, what happens after
146 : * stopping, and how the profile data can be accessed, check the
147 : * documentation of your platform's profiler.
148 : *
149 : * This is NOT thread safe.
150 : *
151 : * @precondition Profiling was started
152 : * @return true if profiling was successfully stopped.
153 : * @see StartProfiling
154 : */
155 : inline bool
156 : StopProfiling()
157 : {
158 : NS_PRECONDITION(gCurrentProfile, "tried to stop profile before starting one");
159 :
160 : const char* profileName = gCurrentProfile;
161 : gCurrentProfile = 0;
162 : return JS_StopProfiling(profileName) ? true : false;
163 : }
164 :
165 : //-----------------------------------------------------------------------------
166 :
167 : class ScopedLogging
168 : {
169 : public:
170 : ScopedLogging()
171 : {
172 : NS_LogInit();
173 : }
174 :
175 : ~ScopedLogging()
176 : {
177 : NS_LogTerm();
178 : }
179 : };
180 :
181 : class ScopedXPCOM : public nsIDirectoryServiceProvider2
182 : {
183 : public:
184 : NS_DECL_ISUPPORTS
185 :
186 20 : ScopedXPCOM(const char* testName,
187 : nsIDirectoryServiceProvider *dirSvcProvider = NULL)
188 20 : : mDirSvcProvider(dirSvcProvider)
189 : {
190 20 : mTestName = testName;
191 20 : printf("Running %s tests...\n", mTestName);
192 :
193 20 : nsresult rv = NS_InitXPCOM2(&mServMgr, NULL, this);
194 20 : if (NS_FAILED(rv))
195 : {
196 0 : fail("NS_InitXPCOM2 returned failure code 0x%x", rv);
197 0 : mServMgr = NULL;
198 0 : return;
199 : }
200 : }
201 :
202 20 : ~ScopedXPCOM()
203 40 : {
204 : // If we created a profile directory, we need to remove it.
205 20 : if (mProfD) {
206 : nsCOMPtr<nsIObserverService> os =
207 40 : do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
208 20 : MOZ_ASSERT(os);
209 20 : if (os) {
210 20 : MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->NotifyObservers(nsnull, "profile-change-net-teardown", nsnull)));
211 20 : MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->NotifyObservers(nsnull, "profile-change-teardown", nsnull)));
212 20 : MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->NotifyObservers(nsnull, "profile-before-change", nsnull)));
213 : }
214 :
215 20 : if (NS_FAILED(mProfD->Remove(true))) {
216 0 : NS_WARNING("Problem removing profile directory");
217 : }
218 :
219 20 : mProfD = nsnull;
220 : }
221 :
222 20 : if (mServMgr)
223 : {
224 20 : NS_RELEASE(mServMgr);
225 20 : nsresult rv = NS_ShutdownXPCOM(NULL);
226 20 : if (NS_FAILED(rv))
227 : {
228 0 : fail("XPCOM shutdown failed with code 0x%x", rv);
229 0 : exit(1);
230 : }
231 : }
232 :
233 20 : printf("Finished running %s tests.\n", mTestName);
234 20 : }
235 :
236 8 : bool failed()
237 : {
238 8 : return mServMgr == NULL;
239 : }
240 :
241 26 : already_AddRefed<nsIFile> GetProfileDirectory()
242 : {
243 26 : if (mProfD) {
244 12 : nsCOMPtr<nsIFile> copy = mProfD;
245 6 : return copy.forget();
246 : }
247 :
248 : // Create a unique temporary folder to use for this test.
249 40 : nsCOMPtr<nsIFile> profD;
250 : nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
251 20 : getter_AddRefs(profD));
252 20 : NS_ENSURE_SUCCESS(rv, nsnull);
253 :
254 20 : rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
255 20 : NS_ENSURE_SUCCESS(rv, nsnull);
256 :
257 20 : rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
258 20 : NS_ENSURE_SUCCESS(rv, nsnull);
259 :
260 20 : mProfD = profD;
261 20 : return profD.forget();
262 : }
263 :
264 : ////////////////////////////////////////////////////////////////////////////
265 : //// nsIDirectoryServiceProvider
266 :
267 163 : NS_IMETHODIMP GetFile(const char *aProperty, bool *_persistent,
268 : nsIFile **_result)
269 : {
270 : // If we were supplied a directory service provider, ask it first.
271 163 : if (mDirSvcProvider &&
272 163 : NS_SUCCEEDED(mDirSvcProvider->GetFile(aProperty, _persistent,
273 : _result))) {
274 0 : return NS_OK;
275 : }
276 :
277 : // Otherwise, the test harness provides some directories automatically.
278 481 : if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
279 159 : 0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
280 159 : 0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
281 48 : nsCOMPtr<nsIFile> profD = GetProfileDirectory();
282 24 : NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
283 :
284 48 : nsCOMPtr<nsIFile> clone;
285 24 : nsresult rv = profD->Clone(getter_AddRefs(clone));
286 24 : NS_ENSURE_SUCCESS(rv, rv);
287 :
288 24 : *_persistent = true;
289 24 : clone.forget(_result);
290 24 : return NS_OK;
291 : }
292 :
293 139 : return NS_ERROR_FAILURE;
294 : }
295 :
296 : ////////////////////////////////////////////////////////////////////////////
297 : //// nsIDirectoryServiceProvider2
298 :
299 40 : NS_IMETHODIMP GetFiles(const char *aProperty, nsISimpleEnumerator **_enum)
300 : {
301 : // If we were supplied a directory service provider, ask it first.
302 : nsCOMPtr<nsIDirectoryServiceProvider2> provider =
303 80 : do_QueryInterface(mDirSvcProvider);
304 40 : if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
305 0 : return NS_OK;
306 : }
307 :
308 40 : return NS_ERROR_FAILURE;
309 : }
310 :
311 : private:
312 : const char* mTestName;
313 : nsIServiceManager* mServMgr;
314 : nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
315 : nsCOMPtr<nsIFile> mProfD;
316 : };
317 :
318 223 : NS_IMPL_QUERY_INTERFACE2(
319 : ScopedXPCOM,
320 : nsIDirectoryServiceProvider,
321 : nsIDirectoryServiceProvider2
322 : )
323 :
324 : NS_IMETHODIMP_(nsrefcnt)
325 243 : ScopedXPCOM::AddRef()
326 : {
327 243 : return 2;
328 : }
329 :
330 : NS_IMETHODIMP_(nsrefcnt)
331 243 : ScopedXPCOM::Release()
332 : {
333 243 : return 1;
334 : }
335 :
336 : #endif // TestHarness_h__
|