1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
15 * The Original Code is Racing Service Manager Test Code.
17 * The Initial Developer of the Original Code is
18 * Ben Turner <bent.mozilla@gmail.com>.
19 * Portions created by the Initial Developer are Copyright (C) 2008
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * 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.
36 * ***** END LICENSE BLOCK ***** */
38 #include "TestHarness.h"
40 #include "nsIFactory.h"
41 #include "nsIThread.h"
42 #include "nsIComponentRegistrar.h"
44 #include "nsAutoLock.h"
45 #include "nsAutoPtr.h"
46 #include "nsThreadUtils.h"
47 #include "nsXPCOMCIDInternal.h"
51 #define TEST_ASSERTION(_test, _msg) \
52 NS_ASSERTION(_test, _msg);
54 #define TEST_ASSERTION(_test, _msg) \
57 NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_test, __FILE__, __LINE__); \
62 /* f93f6bdc-88af-42d7-9d64-1b43c649a3e5 */
63 #define FACTORY_CID1 \
68 { 0x9d, 0x64, 0x1b, 0x43, 0xc6, 0x49, 0xa3, 0xe5 } \
70 NS_DEFINE_CID(kFactoryCID1
, FACTORY_CID1
);
72 /* ef38ad65-6595-49f0-8048-e819f81d15e2 */
73 #define FACTORY_CID2 \
78 { 0x80, 0x48, 0xe8, 0x19, 0xf8, 0x1d, 0x15, 0xe2 } \
80 NS_DEFINE_CID(kFactoryCID2
, FACTORY_CID2
);
82 #define FACTORY_CONTRACTID \
83 "TestRacingThreadManager/factory;1"
85 PRInt32 gComponent1Count
= 0;
86 PRInt32 gComponent2Count
= 0;
88 PRMonitor
* gMonitor
= nsnull
;
90 PRBool gCreateInstanceCalled
= PR_FALSE
;
91 PRBool gMainThreadWaiting
= PR_FALSE
;
93 class AutoCreateAndDestroyMonitor
96 AutoCreateAndDestroyMonitor(PRMonitor
** aMonitorPtr
)
97 : mMonitorPtr(aMonitorPtr
) {
99 nsAutoMonitor::NewMonitor("TestRacingServiceManager::AutoMon");
100 TEST_ASSERTION(*aMonitorPtr
, "Out of memory!");
103 ~AutoCreateAndDestroyMonitor() {
105 nsAutoMonitor::DestroyMonitor(*mMonitorPtr
);
106 *mMonitorPtr
= nsnull
;
111 PRMonitor
** mMonitorPtr
;
114 class Factory
: public nsIFactory
119 Factory() : mFirstComponentCreated(PR_FALSE
) { }
121 NS_IMETHOD
CreateInstance(nsISupports
* aDelegate
,
125 NS_IMETHOD
LockFactory(PRBool aLock
) {
129 PRBool mFirstComponentCreated
;
132 NS_IMPL_THREADSAFE_ISUPPORTS1(Factory
, nsIFactory
)
134 class Component1
: public nsISupports
140 // This is the real test - make sure that only one instance is ever created.
141 PRInt32 count
= PR_AtomicIncrement(&gComponent1Count
);
142 TEST_ASSERTION(count
== 1, "Too many components created!");
146 NS_IMPL_THREADSAFE_ADDREF(Component1
)
147 NS_IMPL_THREADSAFE_RELEASE(Component1
)
149 NS_INTERFACE_MAP_BEGIN(Component1
)
150 NS_INTERFACE_MAP_ENTRY(Component1
)
151 NS_INTERFACE_MAP_ENTRY(nsISupports
)
154 class Component2
: public nsISupports
160 // This is the real test - make sure that only one instance is ever created.
161 PRInt32 count
= PR_AtomicIncrement(&gComponent2Count
);
162 TEST_ASSERTION(count
== 1, "Too many components created!");
166 NS_IMPL_THREADSAFE_ADDREF(Component2
)
167 NS_IMPL_THREADSAFE_RELEASE(Component2
)
169 NS_INTERFACE_MAP_BEGIN(Component2
)
170 NS_INTERFACE_MAP_ENTRY(Component2
)
171 NS_INTERFACE_MAP_ENTRY(nsISupports
)
175 Factory::CreateInstance(nsISupports
* aDelegate
,
179 // Make sure that the second thread beat the main thread to the getService
181 TEST_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
184 nsAutoMonitor
mon(gMonitor
);
186 gCreateInstanceCalled
= PR_TRUE
;
189 mon
.Wait(PR_MillisecondsToInterval(3000));
192 NS_ENSURE_FALSE(aDelegate
, NS_ERROR_NO_AGGREGATION
);
193 NS_ENSURE_ARG_POINTER(aResult
);
195 nsCOMPtr
<nsISupports
> instance
;
197 if (!mFirstComponentCreated
) {
198 instance
= new Component1();
201 instance
= new Component2();
203 NS_ENSURE_TRUE(instance
, NS_ERROR_OUT_OF_MEMORY
);
205 nsresult rv
= instance
->QueryInterface(aIID
, aResult
);
206 NS_ENSURE_SUCCESS(rv
, rv
);
211 class Runnable
: public nsRunnable
216 Runnable() : mFirstRunnableDone(PR_FALSE
) { }
218 PRBool mFirstRunnableDone
;
225 nsAutoMonitor
mon(gMonitor
);
227 while (!gMainThreadWaiting
) {
233 nsCOMPtr
<nsISupports
> component
;
235 if (!mFirstRunnableDone
) {
236 component
= do_GetService(kFactoryCID1
, &rv
);
239 component
= do_GetService(FACTORY_CONTRACTID
, &rv
);
241 TEST_ASSERTION(NS_SUCCEEDED(rv
), "GetService failed!");
246 int main(int argc
, char** argv
)
248 ScopedXPCOM
xpcom("RacingServiceManager");
249 NS_ENSURE_FALSE(xpcom
.failed(), 1);
251 nsCOMPtr
<nsIComponentRegistrar
> registrar
;
252 nsresult rv
= NS_GetComponentRegistrar(getter_AddRefs(registrar
));
253 NS_ENSURE_SUCCESS(rv
, 1);
255 nsRefPtr
<Factory
> factory
= new Factory();
256 NS_ENSURE_TRUE(factory
, 1);
258 rv
= registrar
->RegisterFactory(kFactoryCID1
, nsnull
, nsnull
, factory
);
259 NS_ENSURE_SUCCESS(rv
, 1);
261 rv
= registrar
->RegisterFactory(kFactoryCID2
, nsnull
, FACTORY_CONTRACTID
,
263 NS_ENSURE_SUCCESS(rv
, 1);
265 AutoCreateAndDestroyMonitor
mon(&gMonitor
);
267 nsRefPtr
<Runnable
> runnable
= new Runnable();
268 NS_ENSURE_TRUE(runnable
, 1);
270 // Run the classID test
271 nsCOMPtr
<nsIThread
> newThread
;
272 rv
= NS_NewThread(getter_AddRefs(newThread
), runnable
);
273 NS_ENSURE_SUCCESS(rv
, 1);
276 nsAutoMonitor
mon(gMonitor
);
278 gMainThreadWaiting
= PR_TRUE
;
281 while (!gCreateInstanceCalled
) {
286 nsCOMPtr
<nsISupports
> component(do_GetService(kFactoryCID1
, &rv
));
287 NS_ENSURE_SUCCESS(rv
, 1);
289 // Reset for the contractID test
290 gMainThreadWaiting
= gCreateInstanceCalled
= PR_FALSE
;
291 factory
->mFirstComponentCreated
= runnable
->mFirstRunnableDone
= PR_TRUE
;
294 rv
= newThread
->Dispatch(runnable
, NS_DISPATCH_NORMAL
);
295 NS_ENSURE_SUCCESS(rv
, 1);
298 nsAutoMonitor
mon(gMonitor
);
300 gMainThreadWaiting
= PR_TRUE
;
303 while (!gCreateInstanceCalled
) {
308 component
= do_GetService(FACTORY_CONTRACTID
, &rv
);
309 NS_ENSURE_SUCCESS(rv
, 1);