Bug 545892 - Always pass WM_NCPAINT events to the default event procedure. r=bent...
[mozilla-central.git] / xpcom / tests / TestProxies.cpp
blob25505cda2c8a4c929cb15e812b67f6fd7acb4837
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
13 * License.
15 * The Original Code is Proxy 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.
22 * Contributor(s):
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 "nsIEventTarget.h"
41 #include "nsIProxyObjectManager.h"
42 #include "nsIRunnable.h"
43 #include "nsIThread.h"
44 #include "nsIThreadPool.h"
46 #include "nsAutoPtr.h"
47 #include "nsCOMPtr.h"
48 #include "nsComponentManagerUtils.h"
49 #include "nsServiceManagerUtils.h"
50 #include "nsThreadUtils.h"
51 #include "nsXPCOMCIDInternal.h"
52 #include "prlog.h"
54 #include "mozilla/Mutex.h"
55 using namespace mozilla;
57 typedef nsresult(*TestFuncPtr)();
59 #define TEST_NAME "TestProxies"
61 #ifdef PR_LOGGING
62 static PRLogModuleInfo* sLog = PR_NewLogModule(TEST_NAME);
63 #endif
64 #define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
66 static nsIThread* gMainThread = nsnull;
67 static nsIThread* gTestThread = nsnull;
69 static nsresult
70 GetProxyForObject(nsIEventTarget* aTarget,
71 REFNSIID aIID,
72 nsISupports* aObj,
73 PRInt32 aProxyType,
74 void** aProxyObject)
76 nsresult rv;
77 nsCOMPtr<nsIProxyObjectManager> proxyObjMgr =
78 do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv);
79 NS_ENSURE_SUCCESS(rv, rv);
81 return proxyObjMgr->GetProxyForObject(aTarget, aIID, aObj, aProxyType,
82 aProxyObject);
85 class nsAutoTestThread
87 public:
88 nsAutoTestThread(nsIThread** aGlobal = nsnull)
89 : mGlobal(aGlobal)
91 nsCOMPtr<nsIThread> newThread;
92 nsresult rv = NS_NewThread(getter_AddRefs(newThread));
93 if (NS_FAILED(rv))
94 return;
96 rv = newThread->GetPRThread(&mNativeThread);
97 if (NS_FAILED(rv))
98 return;
100 LOG(("Created test thread [0x%p]", static_cast<void*>(mNativeThread)));
102 newThread.swap(mThread);
104 if (mGlobal)
105 *mGlobal = mThread;
108 ~nsAutoTestThread()
110 if (mGlobal)
111 *mGlobal = nsnull;
113 #ifdef PR_LOGGING
114 void* nativeThread = static_cast<void*>(mNativeThread);
115 #endif
117 LOG(("Shutting down test thread [0x%p]", nativeThread));
118 mThread->Shutdown();
119 LOG(("Test thread successfully shut down [0x%p]", nativeThread));
122 operator nsIThread*() const
124 return mThread;
127 nsIThread* operator->() const
129 return mThread;
132 private:
133 nsIThread** mGlobal;
134 nsCOMPtr<nsIThread> mThread;
135 PRThread* mNativeThread;
138 class SimpleRunnable : public nsRunnable
140 public:
141 SimpleRunnable(const char* aType = "SimpleRunnable")
142 : mType(aType)
145 NS_IMETHOD Run()
147 LOG(("%s::Run() [0x%p]", mType,
148 static_cast<void*>(static_cast<nsISupports*>(this))));
149 return NS_OK;
151 private:
152 const char* mType;
155 class TestTargetThreadRunnable : public SimpleRunnable
157 public:
158 TestTargetThreadRunnable(nsIThread* aTarget)
159 : SimpleRunnable("TestTargetThreadRunnable"),
160 mTarget(aTarget)
163 NS_IMETHOD Run()
165 nsresult rv = SimpleRunnable::Run();
166 NS_ENSURE_SUCCESS(rv, rv);
168 nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
169 if (currentThread != mTarget) {
170 NS_ERROR("Proxy sent call to wrong thread!");
171 return NS_ERROR_FAILURE;
174 return NS_OK;
177 private:
178 nsCOMPtr<nsIThread> mTarget;
181 class ChainedProxyRunnable : public SimpleRunnable
183 public:
184 ChainedProxyRunnable(nsIThread* aSecondTarget,
185 nsIThread* aThirdTarget = nsnull)
186 : SimpleRunnable("ChainedProxyRunnable"), mSecondTarget(aSecondTarget),
187 mThirdTarget(aThirdTarget)
190 NS_IMETHOD Run()
192 nsresult rv = SimpleRunnable::Run();
193 NS_ENSURE_SUCCESS(rv, rv);
195 nsRefPtr<SimpleRunnable> runnable = mThirdTarget ?
196 new ChainedProxyRunnable(mThirdTarget) :
197 new SimpleRunnable();
198 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
200 nsCOMPtr<nsIRunnable> proxy;
201 rv = GetProxyForObject(mSecondTarget, NS_GET_IID(nsIRunnable), runnable,
202 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
203 getter_AddRefs(proxy));
204 NS_ENSURE_SUCCESS(rv, rv);
206 rv = proxy->Run();
207 NS_ENSURE_SUCCESS(rv, rv);
209 return NS_OK;
212 private:
213 nsCOMPtr<nsIThread> mSecondTarget;
214 nsCOMPtr<nsIThread> mThirdTarget;
217 class IncrementingRunnable : public SimpleRunnable
219 public:
220 IncrementingRunnable(PRUint32* aCounter, Mutex* aLock = nsnull)
221 : SimpleRunnable("IncrementingRunnable"), mCounter(aCounter), mLock(aLock)
224 NS_IMETHOD Run()
226 nsresult rv = SimpleRunnable::Run();
227 NS_ENSURE_SUCCESS(rv, rv);
229 if (mLock)
230 mLock->Lock();
232 (*mCounter)++;
234 if (mLock)
235 mLock->Unlock();
237 return NS_OK;
240 private:
241 PRUint32* mCounter;
242 Mutex* mLock;
245 class NonThreadsafeRunnable : public nsIRunnable
247 public:
248 NS_DECL_ISUPPORTS
250 NonThreadsafeRunnable(PRUint32* aCounter,
251 const char* aType = "NonThreadsafeRunnable")
252 : mCounter(aCounter),
253 mType(aType)
256 virtual ~NonThreadsafeRunnable()
257 { };
259 NS_IMETHOD Run()
261 LOG(("%s::Run() [0x%p]", mType,
262 static_cast<void*>(static_cast<nsISupports*>(this))));
264 (*mCounter)++;
265 return NS_OK;
268 private:
269 PRUint32* mCounter;
270 const char* mType;
273 NS_IMPL_ISUPPORTS1(NonThreadsafeRunnable, nsIRunnable)
275 class MainThreadRunnable : public NonThreadsafeRunnable
277 public:
278 NS_DECL_ISUPPORTS_INHERITED
280 MainThreadRunnable(PRUint32* aCounter)
281 : NonThreadsafeRunnable(aCounter, "MainThreadRunnable")
283 if (!NS_IsMainThread()) {
284 NS_ERROR("Not running on the main thread!");
288 virtual ~MainThreadRunnable()
290 if (!NS_IsMainThread()) {
291 NS_ERROR("Not running on the main thread!");
295 NS_IMETHOD Run()
297 if (!NS_IsMainThread()) {
298 NS_ERROR("Not running on the main thread!");
299 return NS_ERROR_FAILURE;
302 nsresult rv = NonThreadsafeRunnable::Run();
303 NS_ENSURE_SUCCESS(rv, rv);
305 return NS_OK;
309 NS_IMPL_ISUPPORTS_INHERITED0(MainThreadRunnable, NonThreadsafeRunnable)
311 class ProxyGetter : public nsRunnable
313 public:
314 ProxyGetter(nsIRunnable* aRunnable, nsIRunnable** retval)
315 : mRunnable(aRunnable), _retval(retval)
318 NS_IMETHOD Run()
320 *_retval = nsnull;
322 if (NS_IsMainThread()) {
323 NS_ERROR("Shouldn't be running on the main thread!");
324 return NS_ERROR_FAILURE;
327 nsCOMPtr<nsIRunnable> proxy;
328 nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
329 mRunnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
330 getter_AddRefs(proxy));
331 NS_ENSURE_SUCCESS(rv, rv);
333 proxy.forget(_retval);
334 return NS_OK;
337 private:
338 nsIRunnable* mRunnable;
339 nsIRunnable** _retval;
342 class RunnableGetter : public nsRunnable
344 public:
345 RunnableGetter(PRUint32* aCounter, nsIRunnable** retval)
346 : mCounter(aCounter), _retval(retval)
349 NS_IMETHOD Run()
351 *_retval = nsnull;
353 if (NS_IsMainThread()) {
354 NS_ERROR("Shouldn't be running on the main thread!");
355 return NS_ERROR_FAILURE;
358 nsCOMPtr<nsIRunnable> runnable = new NonThreadsafeRunnable(mCounter);
359 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
361 runnable.forget(_retval);
362 return NS_OK;
365 private:
366 PRUint32* mCounter;
367 nsIRunnable** _retval;
370 nsresult
371 TestTargetThread()
373 LOG(("--- Running TestTargetThread ---"));
375 nsRefPtr<TestTargetThreadRunnable> runnable =
376 new TestTargetThreadRunnable(gMainThread);
377 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
379 nsCOMPtr<nsIRunnable> proxy;
380 nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
381 runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
382 getter_AddRefs(proxy));
383 NS_ENSURE_SUCCESS(rv, rv);
385 rv = proxy->Run();
386 NS_ENSURE_SUCCESS(rv, rv);
388 runnable = new TestTargetThreadRunnable(gTestThread);
389 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
391 rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
392 NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxy));
393 NS_ENSURE_SUCCESS(rv, rv);
395 rv = proxy->Run();
396 NS_ENSURE_SUCCESS(rv, rv);
398 return NS_OK;
401 nsresult
402 TestNonThreadsafeProxy()
404 LOG(("--- Running TestNonThreadsafeProxy 1 ---"));
406 // Make sure a non-threadsafe object and proxy to it (both created on the same
407 // thread) can be used on the same thread.
409 PRUint32 counter = 0;
410 nsCOMPtr<nsIRunnable> runnable(new MainThreadRunnable(&counter));
411 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
413 nsCOMPtr<nsIRunnable> proxy;
414 nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
415 runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
416 getter_AddRefs(proxy));
417 NS_ENSURE_SUCCESS(rv, rv);
419 for (PRUint32 otherCounter = 0; otherCounter < 5;) {
420 rv = gTestThread->Dispatch(proxy, NS_DISPATCH_SYNC);
421 NS_ENSURE_SUCCESS(rv, rv);
422 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
425 // Make sure a non-threadsafe object and proxy to it (both created on the same
426 // thread) can be used on a different thread.
428 LOG(("--- Running TestNonThreadsafeProxy 2 ---"));
430 counter = 0;
431 runnable = new NonThreadsafeRunnable(&counter);
432 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
434 rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
435 runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
436 getter_AddRefs(proxy));
437 NS_ENSURE_SUCCESS(rv, rv);
439 runnable = nsnull;
441 for (PRUint32 otherCounter = 0; otherCounter < 5;) {
442 rv = proxy->Run();
443 NS_ENSURE_SUCCESS(rv, rv);
444 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
447 NS_ENSURE_TRUE(counter == 5, NS_ERROR_FAILURE);
449 // Make sure a non-threadsafe object and proxy to it (created on different
450 // threads) can be used by any thread.
452 LOG(("--- Running TestNonThreadsafeProxy 3 ---"));
454 counter = 0;
455 proxy = nsnull;
457 runnable = new MainThreadRunnable(&counter);
458 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
460 nsCOMPtr<nsIRunnable> proxyGetter =
461 new ProxyGetter(runnable, getter_AddRefs(proxy));
462 NS_ENSURE_TRUE(proxyGetter, NS_ERROR_OUT_OF_MEMORY);
464 rv = gTestThread->Dispatch(proxyGetter, NS_DISPATCH_SYNC);
465 NS_ENSURE_SUCCESS(rv, rv);
466 NS_ENSURE_TRUE(proxy, NS_ERROR_FAILURE);
468 for (PRUint32 otherCounter = 0; otherCounter < 5;) {
469 rv = proxy->Run();
470 NS_ENSURE_SUCCESS(rv, rv);
471 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
474 // Make sure a non-threadsafe object (created on thread 1) and proxy to it
475 // (created on thread 2) can be used by thread 3.
477 LOG(("--- Running TestNonThreadsafeProxy 4 ---"));
479 counter = 0;
480 proxy = nsnull;
481 runnable = nsnull;
483 nsCOMPtr<nsIRunnable> runnableGetter =
484 new RunnableGetter(&counter, getter_AddRefs(runnable));
485 NS_ENSURE_TRUE(runnableGetter, NS_ERROR_OUT_OF_MEMORY);
487 rv = gTestThread->Dispatch(runnableGetter, NS_DISPATCH_SYNC);
488 NS_ENSURE_SUCCESS(rv, rv);
489 NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);
491 proxyGetter = new ProxyGetter(runnable, getter_AddRefs(proxy));
492 NS_ENSURE_TRUE(proxyGetter, NS_ERROR_OUT_OF_MEMORY);
494 nsAutoTestThread otherTestThread;
495 NS_ENSURE_TRUE(otherTestThread, NS_ERROR_FAILURE);
497 rv = otherTestThread->Dispatch(proxyGetter, NS_DISPATCH_SYNC);
498 NS_ENSURE_SUCCESS(rv, rv);
499 NS_ENSURE_TRUE(proxy, NS_ERROR_FAILURE);
501 for (PRUint32 otherCounter = 0; otherCounter < 5;) {
502 rv = proxy->Run();
503 NS_ENSURE_SUCCESS(rv, rv);
504 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
507 return NS_OK;
510 nsresult
511 TestChainedProxy()
513 LOG(("--- Running TestChainedProxy ---"));
515 nsRefPtr<ChainedProxyRunnable> runnable =
516 new ChainedProxyRunnable(gMainThread);
517 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
519 nsCOMPtr<nsIRunnable> proxy;
520 nsresult rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
521 runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
522 getter_AddRefs(proxy));
523 NS_ENSURE_SUCCESS(rv, rv);
525 // This will do a test->main call
526 rv = proxy->Run();
527 NS_ENSURE_SUCCESS(rv, rv);
529 runnable = new ChainedProxyRunnable(gTestThread);
530 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
532 rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
533 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
534 getter_AddRefs(proxy));
535 NS_ENSURE_SUCCESS(rv, rv);
537 // This will do a main->test call
538 rv = proxy->Run();
539 NS_ENSURE_SUCCESS(rv, rv);
541 runnable = new ChainedProxyRunnable(gMainThread);
542 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
544 rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
545 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
546 getter_AddRefs(proxy));
547 NS_ENSURE_SUCCESS(rv, rv);
549 // This will do a main->main call
550 rv = proxy->Run();
551 NS_ENSURE_SUCCESS(rv, rv);
553 runnable = new ChainedProxyRunnable(gTestThread);
554 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
556 rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
557 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
558 getter_AddRefs(proxy));
559 NS_ENSURE_SUCCESS(rv, rv);
561 // This will do a test->test call
562 rv = proxy->Run();
563 NS_ENSURE_SUCCESS(rv, rv);
565 runnable = new ChainedProxyRunnable(gMainThread, gTestThread);
566 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
568 rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
569 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
570 getter_AddRefs(proxy));
571 NS_ENSURE_SUCCESS(rv, rv);
573 // This will do a test->main->test call
574 rv = proxy->Run();
575 NS_ENSURE_SUCCESS(rv, rv);
577 return NS_OK;
580 nsresult
581 TestReleaseOfRealObjects()
583 LOG(("--- Running TestReleaseOfRealObjects ---"));
585 PRUint32 counter = 0, otherCounter = 0;
587 nsRefPtr<IncrementingRunnable> runnable(new IncrementingRunnable(&counter));
588 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
590 nsCOMPtr<nsIRunnable> proxy1;
591 nsresult rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
592 runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
593 getter_AddRefs(proxy1));
594 NS_ENSURE_SUCCESS(rv, rv);
596 nsCOMPtr<nsIRunnable> proxy2;
597 rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
598 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
599 getter_AddRefs(proxy2));
600 NS_ENSURE_SUCCESS(rv, rv);
602 nsCOMPtr<nsIRunnable> proxy3;
603 rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
604 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
605 getter_AddRefs(proxy3));
606 NS_ENSURE_SUCCESS(rv, rv);
608 NS_ENSURE_FALSE(proxy1 == proxy2, NS_ERROR_FAILURE);
609 NS_ENSURE_TRUE(proxy2 == proxy3, NS_ERROR_FAILURE);
610 proxy3 = nsnull;
612 rv = proxy1->Run();
613 NS_ENSURE_SUCCESS(rv, rv);
614 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
616 rv = proxy2->Run();
617 NS_ENSURE_SUCCESS(rv, rv);
618 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
620 runnable = nsnull;
622 rv = proxy1->Run();
623 NS_ENSURE_SUCCESS(rv, rv);
624 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
626 rv = proxy2->Run();
627 NS_ENSURE_SUCCESS(rv, rv);
628 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
630 proxy1 = nsnull;
632 rv = proxy2->Run();
633 NS_ENSURE_SUCCESS(rv, rv);
634 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
636 return NS_OK;
639 nsresult
640 TestCurrentThreadProxy()
642 LOG(("--- Running TestCurrentThreadProxy ---"));
644 PRUint32 counter = 0, otherCounter = 0;
645 nsRefPtr<IncrementingRunnable> runnable(new IncrementingRunnable(&counter));
646 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
648 nsCOMPtr<nsIRunnable> proxy1;
649 nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
650 runnable, NS_PROXY_SYNC,
651 getter_AddRefs(proxy1));
652 NS_ENSURE_SUCCESS(rv, rv);
654 nsCOMPtr<nsIRunnable> proxy2;
655 rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
656 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
657 getter_AddRefs(proxy2));
658 NS_ENSURE_SUCCESS(rv, rv);
660 NS_ENSURE_FALSE(proxy1 == proxy2, NS_ERROR_FAILURE);
662 nsCOMPtr<nsIRunnable> realRunnable(do_QueryInterface(runnable));
663 NS_ENSURE_TRUE(realRunnable, NS_ERROR_FAILURE);
665 NS_ENSURE_TRUE(static_cast<void*>(realRunnable) == static_cast<void*>(runnable),
666 NS_ERROR_FAILURE);
668 rv = proxy1->Run();
669 NS_ENSURE_SUCCESS(rv, rv);
670 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
672 rv = proxy2->Run();
673 NS_ENSURE_SUCCESS(rv, rv);
674 NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
676 return NS_OK;
679 nsresult
680 TestAsyncProxy()
682 LOG(("--- Running TestAsyncProxy ---"));
684 // Test async proxies to the current thread.
686 PRUint32 counter = 0;
687 nsRefPtr<SimpleRunnable> runnable(new IncrementingRunnable(&counter));
688 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
690 nsCOMPtr<nsIRunnable> proxy;
691 nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
692 runnable, NS_PROXY_ASYNC,
693 getter_AddRefs(proxy));
694 NS_ENSURE_SUCCESS(rv, rv);
696 runnable = nsnull;
698 for (PRUint32 i = 0; i < 5; i++) {
699 rv = proxy->Run();
700 NS_ENSURE_SUCCESS(rv, rv);
703 while (counter < 5) {
704 rv = NS_ProcessPendingEvents(gMainThread, PR_SecondsToInterval(1));
705 NS_ENSURE_SUCCESS(rv, rv);
708 // Now test async proxies to another thread.
710 Mutex* counterLock = new Mutex("counterLock");
711 NS_ENSURE_TRUE(counterLock, NS_ERROR_OUT_OF_MEMORY);
713 counter = 0;
714 runnable = new IncrementingRunnable(&counter, counterLock);
715 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
717 rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
718 NS_PROXY_ASYNC, getter_AddRefs(proxy));
719 NS_ENSURE_SUCCESS(rv, rv);
721 for (PRUint32 i = 0; i < 5; i++) {
722 rv = proxy->Run();
723 NS_ENSURE_SUCCESS(rv, rv);
726 PRUint32 safeCounter = 0;
727 while (safeCounter < 5) {
728 rv = NS_ProcessPendingEvents(gMainThread, PR_SecondsToInterval(1));
729 NS_ENSURE_SUCCESS(rv, rv);
731 MutexAutoLock lock(*counterLock);
732 safeCounter = counter;
735 delete counterLock;
737 // Now test async proxies to another thread that create sync proxies to this
738 // thread.
740 runnable = new ChainedProxyRunnable(gMainThread);
741 NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
743 rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
744 runnable, NS_PROXY_ASYNC,
745 getter_AddRefs(proxy));
746 NS_ENSURE_SUCCESS(rv, rv);
748 rv = proxy->Run();
749 NS_ENSURE_SUCCESS(rv, rv);
751 // That was async, so make sure to wait for all the events on the test thread
752 // to be processed before we return. This is easy to do with an empty sync
753 // event.
754 nsCOMPtr<nsIRunnable> flusher = new nsRunnable();
755 NS_ENSURE_TRUE(flusher, NS_ERROR_OUT_OF_MEMORY);
757 LOG(("Flushing events on test thread"));
759 rv = gTestThread->Dispatch(flusher, NS_DISPATCH_SYNC);
760 NS_ENSURE_SUCCESS(rv, rv);
762 LOG(("Flushing events completed"));
764 return NS_OK;
767 int main(int argc, char** argv)
769 ScopedXPCOM xpcom(TEST_NAME);
770 NS_ENSURE_FALSE(xpcom.failed(), 1);
772 nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
773 NS_ENSURE_TRUE(mainThread, 1);
775 LOG(("Got main thread"));
776 gMainThread = mainThread;
778 nsAutoTestThread testThread(&gTestThread);
779 NS_ENSURE_TRUE(testThread, 1);
781 static TestFuncPtr testsToRun[] = {
782 TestTargetThread,
783 // TestNonThreadsafeProxy, /* Not currently supported! */
784 TestChainedProxy,
785 TestReleaseOfRealObjects,
786 TestCurrentThreadProxy,
787 TestAsyncProxy
789 static PRUint32 testCount = sizeof(testsToRun) / sizeof(testsToRun[0]);
791 for (PRUint32 i = 0; i < testCount; i++) {
792 nsresult rv = testsToRun[i]();
793 NS_ENSURE_SUCCESS(rv, 1);
796 LOG(("--- Finished all tests ---"));
797 return 0;