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 27 : void passed(const char* msg, ...)
102 : {
103 : va_list ap;
104 :
105 27 : printf("TEST-PASS | ");
106 :
107 27 : va_start(ap, msg);
108 27 : vprintf(msg, ap);
109 27 : va_end(ap);
110 :
111 27 : putchar('\n');
112 27 : }
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 1 : ScopedLogging()
171 : {
172 1 : NS_LogInit();
173 1 : }
174 :
175 1 : ~ScopedLogging()
176 : {
177 1 : NS_LogTerm();
178 1 : }
179 : };
180 :
181 : class ScopedXPCOM : public nsIDirectoryServiceProvider2
182 : {
183 : public:
184 : NS_DECL_ISUPPORTS
185 :
186 10 : ScopedXPCOM(const char* testName,
187 : nsIDirectoryServiceProvider *dirSvcProvider = NULL)
188 10 : : mDirSvcProvider(dirSvcProvider)
189 : {
190 10 : mTestName = testName;
191 10 : printf("Running %s tests...\n", mTestName);
192 :
193 10 : nsresult rv = NS_InitXPCOM2(&mServMgr, NULL, this);
194 10 : 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 10 : ~ScopedXPCOM()
203 20 : {
204 : // If we created a profile directory, we need to remove it.
205 10 : if (mProfD) {
206 : nsCOMPtr<nsIObserverService> os =
207 20 : do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
208 10 : MOZ_ASSERT(os);
209 10 : if (os) {
210 10 : MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->NotifyObservers(nsnull, "profile-change-net-teardown", nsnull)));
211 10 : MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->NotifyObservers(nsnull, "profile-change-teardown", nsnull)));
212 10 : MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->NotifyObservers(nsnull, "profile-before-change", nsnull)));
213 : }
214 :
215 10 : if (NS_FAILED(mProfD->Remove(true))) {
216 0 : NS_WARNING("Problem removing profile directory");
217 : }
218 :
219 10 : mProfD = nsnull;
220 : }
221 :
222 10 : if (mServMgr)
223 : {
224 10 : NS_RELEASE(mServMgr);
225 10 : nsresult rv = NS_ShutdownXPCOM(NULL);
226 10 : if (NS_FAILED(rv))
227 : {
228 0 : fail("XPCOM shutdown failed with code 0x%x", rv);
229 0 : exit(1);
230 : }
231 : }
232 :
233 10 : printf("Finished running %s tests.\n", mTestName);
234 10 : }
235 :
236 10 : bool failed()
237 : {
238 10 : return mServMgr == NULL;
239 : }
240 :
241 10 : already_AddRefed<nsIFile> GetProfileDirectory()
242 : {
243 10 : if (mProfD) {
244 0 : nsCOMPtr<nsIFile> copy = mProfD;
245 0 : return copy.forget();
246 : }
247 :
248 : // Create a unique temporary folder to use for this test.
249 20 : nsCOMPtr<nsIFile> profD;
250 : nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
251 10 : getter_AddRefs(profD));
252 10 : NS_ENSURE_SUCCESS(rv, nsnull);
253 :
254 10 : rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
255 10 : NS_ENSURE_SUCCESS(rv, nsnull);
256 :
257 10 : rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
258 10 : NS_ENSURE_SUCCESS(rv, nsnull);
259 :
260 10 : mProfD = profD;
261 10 : return profD.forget();
262 : }
263 :
264 : ////////////////////////////////////////////////////////////////////////////
265 : //// nsIDirectoryServiceProvider
266 :
267 71 : 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 71 : if (mDirSvcProvider &&
272 71 : 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 213 : if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
279 71 : 0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
280 71 : 0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
281 20 : nsCOMPtr<nsIFile> profD = GetProfileDirectory();
282 10 : NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
283 :
284 20 : nsCOMPtr<nsIFile> clone;
285 10 : nsresult rv = profD->Clone(getter_AddRefs(clone));
286 10 : NS_ENSURE_SUCCESS(rv, rv);
287 :
288 10 : *_persistent = true;
289 10 : clone.forget(_result);
290 10 : return NS_OK;
291 : }
292 :
293 61 : return NS_ERROR_FAILURE;
294 : }
295 :
296 : ////////////////////////////////////////////////////////////////////////////
297 : //// nsIDirectoryServiceProvider2
298 :
299 20 : 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 40 : do_QueryInterface(mDirSvcProvider);
304 20 : if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
305 0 : return NS_OK;
306 : }
307 :
308 20 : 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 101 : NS_IMPL_QUERY_INTERFACE2(
319 : ScopedXPCOM,
320 : nsIDirectoryServiceProvider,
321 : nsIDirectoryServiceProvider2
322 : )
323 :
324 : NS_IMETHODIMP_(nsrefcnt)
325 111 : ScopedXPCOM::AddRef()
326 : {
327 111 : return 2;
328 : }
329 :
330 : NS_IMETHODIMP_(nsrefcnt)
331 111 : ScopedXPCOM::Release()
332 : {
333 111 : return 1;
334 : }
335 :
336 : #endif // TestHarness_h__
|