Back to index

lightning-sunbird  0.9+nobinonly
proxytests.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include <stdio.h>
00040 
00041 #include "nsXPCOM.h"
00042 #include "nsIComponentManager.h"
00043 #include "nsIComponentRegistrar.h"
00044 #include "nsIServiceManager.h"
00045 #include "nsCOMPtr.h"
00046 
00047 #include "nscore.h"
00048 #include "nspr.h"
00049 #include "prmon.h"
00050 
00051 #include "nsITestProxy.h"
00052 
00053 #include "nsIProxyObjectManager.h"
00054 #include "nsIEventQueueService.h"
00055 
00056 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00057 
00058 /***************************************************************************/
00059 /* nsTestXPCFoo                                                            */
00060 /***************************************************************************/
00061 class nsTestXPCFoo : public nsITestProxy
00062 {
00063     NS_DECL_ISUPPORTS
00064     NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
00065     NS_IMETHOD Test2();
00066     NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
00067 
00068     nsTestXPCFoo();
00069 };
00070 
00071 nsTestXPCFoo::nsTestXPCFoo()
00072 {
00073     NS_ADDREF_THIS();
00074 }
00075 
00076 NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy)
00077 
00078 NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
00079 {
00080     printf("Thread (%d) Test Called successfully! Party on...\n", p1);
00081     *retval = p1+p2;
00082     return NS_OK;
00083 }
00084 
00085 
00086 NS_IMETHODIMP nsTestXPCFoo::Test2()
00087 {
00088     printf("The quick brown netscape jumped over the old lazy ie..\n");
00089 
00090     return NS_OK;
00091 }
00092 
00093 NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2)
00094 {
00095     if (p1 != nsnull)
00096     {
00097         nsITestProxy *test;
00098 
00099         p1->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
00100         
00101         test->Test2();
00102         PRInt32 a;
00103         test->Test( 1, 2, &a);
00104         printf("\n1+2=%d\n",a);
00105     }
00106 
00107 
00108     *p2 = new nsTestXPCFoo();
00109     return NS_OK;
00110 }
00111 
00112 /***************************************************************************/
00113 /* nsTestXPCFoo2                                                           */
00114 /***************************************************************************/
00115 class nsTestXPCFoo2 : public nsITestProxy
00116 {
00117     NS_DECL_ISUPPORTS
00118     NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
00119     NS_IMETHOD Test2();
00120     NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
00121 
00122     nsTestXPCFoo2();
00123 };
00124 
00125 nsTestXPCFoo2::nsTestXPCFoo2()
00126 {
00127     NS_ADDREF_THIS();
00128 }
00129 
00130 NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy)
00131 
00132 NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
00133 {
00134     printf("calling back to caller!\n\n");
00135 
00136     nsCOMPtr<nsIProxyObjectManager> manager =
00137             do_GetService(NS_XPCOMPROXY_CONTRACTID);
00138 
00139     printf("ProxyObjectManager: %p \n", (void *) manager.get());
00140     
00141     PR_ASSERT(manager);
00142 
00143     nsCOMPtr<nsITestProxy> proxyObject;
00144     manager->GetProxyForObject((nsIEventQueue*)p1, NS_GET_IID(nsITestProxy),
00145                                this, PROXY_SYNC, (void**)&proxyObject);
00146     proxyObject->Test3(nsnull, nsnull);
00147     
00148     printf("Deleting Proxy Object\n");
00149     return NS_OK;
00150 }
00151 
00152 
00153 NS_IMETHODIMP nsTestXPCFoo2::Test2()
00154 {
00155     printf("nsTestXPCFoo2::Test2() called\n");
00156 
00157     return NS_OK;
00158 }
00159 
00160 
00161 NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2)
00162 {
00163     printf("Got called");
00164     return NS_OK;
00165 }
00166 
00167 
00168 
00169 typedef struct _ArgsStruct
00170 {
00171     nsIEventQueue* queue;
00172     PRInt32           threadNumber;
00173 }ArgsStruct;
00174 
00175 
00176 
00177 // This will create two objects both descendants of a single IID.
00178 void TestCase_TwoClassesOneInterface(void *arg)
00179 {
00180     ArgsStruct *argsStruct = (ArgsStruct*) arg;
00181 
00182 
00183     nsCOMPtr<nsIProxyObjectManager> manager =
00184             do_GetService(NS_XPCOMPROXY_CONTRACTID);
00185 
00186     printf("ProxyObjectManager: %p \n", (void *) manager.get());
00187     
00188     PR_ASSERT(manager);
00189 
00190     nsITestProxy         *proxyObject;
00191     nsITestProxy         *proxyObject2;
00192 
00193     nsTestXPCFoo*        foo   = new nsTestXPCFoo();
00194     nsTestXPCFoo2*       foo2  = new nsTestXPCFoo2();
00195     
00196     PR_ASSERT(foo);
00197     PR_ASSERT(foo2);
00198     
00199     
00200     manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
00201     
00202     manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo2, PROXY_SYNC, (void**)&proxyObject2);
00203 
00204     
00205     
00206     if (proxyObject && proxyObject2)
00207     {
00208     // release ownership of the real object. 
00209         
00210         PRInt32 a;
00211         nsresult rv;
00212         PRInt32 threadNumber = argsStruct->threadNumber;
00213         
00214         printf("Deleting real Object (%d)\n", threadNumber);
00215         NS_RELEASE(foo);
00216    
00217         printf("Deleting real Object 2 (%d)\n", threadNumber);
00218         NS_RELEASE(foo2);
00219 
00220 
00221         printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
00222         rv = proxyObject->Test(threadNumber, 0, &a);   
00223         printf("Thread (%d) error: %d.\n", threadNumber, rv);
00224 
00225 
00226         printf("Thread (%d) Prior to calling proxyObject->Test2.\n", threadNumber);
00227         rv = proxyObject->Test2();   
00228         printf("Thread (%d) error: %d.\n", threadNumber, rv);
00229 
00230         printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber);
00231         rv = proxyObject2->Test2();   
00232         printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
00233 
00234         printf("Deleting Proxy Object (%d)\n", threadNumber );
00235         NS_RELEASE(proxyObject);
00236 
00237         printf("Deleting Proxy Object 2 (%d)\n", threadNumber );
00238         NS_RELEASE(proxyObject2);
00239     }    
00240 
00241     PR_Sleep( PR_MillisecondsToInterval(1000) );  // If your thread goes away, your stack goes away.  Only use ASYNC on calls that do not have out parameters
00242 }
00243 
00244 
00245 
00246 void TestCase_NestedLoop(void *arg)
00247 {
00248     ArgsStruct *argsStruct = (ArgsStruct*) arg;
00249 
00250     nsCOMPtr<nsIProxyObjectManager> manager =
00251             do_GetService(NS_XPCOMPROXY_CONTRACTID);
00252 
00253     printf("ProxyObjectManager: %p\n", (void *) manager.get());
00254     
00255     PR_ASSERT(manager);
00256 
00257     nsITestProxy         *proxyObject;
00258     nsTestXPCFoo2*        foo   = new nsTestXPCFoo2();
00259     
00260     PR_ASSERT(foo);
00261     
00262     
00263     manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
00264     
00265     if (proxyObject)
00266     {
00267         // release ownership of the real object. 
00268         
00269         nsresult rv;
00270         PRInt32 threadNumber = argsStruct->threadNumber;
00271         
00272         printf("Deleting real Object (%d)\n", threadNumber);
00273         NS_RELEASE(foo);
00274    
00275         PRInt32 retval;
00276         
00277         printf("Getting EventQueue...\n");
00278 
00279         nsIEventQueue* eventQ;
00280         nsCOMPtr<nsIEventQueueService> eventQService = 
00281                  do_GetService(kEventQueueServiceCID, &rv);
00282         if (NS_SUCCEEDED(rv)) 
00283         {
00284             rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
00285             if (NS_FAILED(rv))
00286                 rv = eventQService->CreateThreadEventQueue();
00287             if (NS_FAILED(rv))
00288                 return;
00289             else
00290                 rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
00291         
00292             printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
00293             rv = proxyObject->Test(NS_PTR_TO_INT32(eventQ), 0, &retval);   
00294             printf("Thread (%d) proxyObject error: %d.\n", threadNumber, rv);
00295 
00296             printf("Deleting Proxy Object (%d)\n", threadNumber );
00297             NS_RELEASE(proxyObject);
00298         }    
00299 
00300         PR_Sleep( PR_MillisecondsToInterval(1000) );  // If your thread goes away, your stack goes away.  Only use ASYNC on calls that do not have out parameters
00301     }
00302 }
00303 
00304 
00305 
00306 void TestCase_2(void *arg)
00307 {
00308 
00309     ArgsStruct *argsStruct = (ArgsStruct*) arg;
00310 
00311     nsCOMPtr<nsIProxyObjectManager> manager =
00312             do_GetService(NS_XPCOMPROXY_CONTRACTID);
00313     
00314     PR_ASSERT(manager);
00315 
00316     nsITestProxy         *proxyObject;
00317 
00318     manager->GetProxy(argsStruct->queue,
00319                             NS_GET_IID(nsITestProxy),   // should be CID!
00320                             nsnull, 
00321                             NS_GET_IID(nsITestProxy), 
00322                             PROXY_SYNC, 
00323                             (void**)&proxyObject);
00324     
00325     if (proxyObject != nsnull)
00326     {
00327         NS_RELEASE(proxyObject);
00328     }
00329 }
00330 
00331 
00332 
00333 void TestCase_nsISupports(void *arg)
00334 {
00335 
00336     ArgsStruct *argsStruct = (ArgsStruct*) arg;
00337 
00338     nsCOMPtr<nsIProxyObjectManager> manager =
00339             do_GetService(NS_XPCOMPROXY_CONTRACTID);
00340     
00341     PR_ASSERT(manager);
00342 
00343     nsITestProxy         *proxyObject;
00344     nsTestXPCFoo*         foo   = new nsTestXPCFoo();
00345     
00346     PR_ASSERT(foo);
00347 
00348      manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
00349     
00350     if (proxyObject != nsnull)
00351     {   
00352         nsISupports *bISupports = nsnull, *cISupports = nsnull;
00353         
00354         proxyObject->Test3(foo, &bISupports);
00355         proxyObject->Test3(bISupports, &cISupports);
00356         
00357         nsITestProxy *test;
00358         bISupports->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
00359         
00360         test->Test2();
00361 
00362         NS_RELEASE(foo);
00363         NS_RELEASE(proxyObject);
00364     }
00365 }
00366 
00367 
00368 
00369 
00370 
00371 /***************************************************************************/
00372 /* ProxyTest                                                               */
00373 /***************************************************************************/
00374 
00375 static void PR_CALLBACK ProxyTest( void *arg )
00376 {
00377    //TestCase_TwoClassesOneInterface(arg);
00378    // TestCase_2(arg);
00379    //TestCase_nsISupports(arg);
00380    TestCase_NestedLoop(arg);
00381 
00382    NS_RELEASE( ((ArgsStruct*) arg)->queue);
00383    free((void*) arg);
00384 }
00385 
00386 nsIEventQueue *gEventQueue = nsnull;
00387 
00388 static void PR_CALLBACK EventLoop( void *arg )
00389 {
00390     nsresult rv;
00391     printf("Creating EventQueue...\n");
00392 
00393     nsIEventQueue* eventQ;
00394     nsCOMPtr<nsIEventQueueService> eventQService = 
00395              do_GetService(kEventQueueServiceCID, &rv);
00396     if (NS_SUCCEEDED(rv)) {
00397       rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
00398       if (NS_FAILED(rv))
00399           rv = eventQService->CreateThreadEventQueue();
00400       if (NS_FAILED(rv))
00401           return;
00402       else
00403           rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
00404     }
00405     if (NS_FAILED(rv)) return;
00406 
00407     rv = eventQ->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&gEventQueue);
00408     if (NS_FAILED(rv)) return;
00409      
00410 
00411     printf("Verifing calling Proxy on eventQ thread.\n");
00412 
00413     nsCOMPtr<nsIProxyObjectManager> manager =
00414             do_GetService(NS_XPCOMPROXY_CONTRACTID);
00415     
00416     PR_ASSERT(manager);
00417 
00418     nsITestProxy         *proxyObject;
00419     nsTestXPCFoo*         foo   = new nsTestXPCFoo();
00420     
00421     PR_ASSERT(foo);
00422 
00423     manager->GetProxyForObject(gEventQueue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
00424 
00425     PRInt32 a;
00426     proxyObject->Test(1, 2, &a);
00427     proxyObject->Test2();
00428 
00429     
00430     NS_RELEASE(proxyObject);
00431     delete foo;
00432 
00433     printf("End of Verification calling Proxy on eventQ thread.\n");
00434 
00435 
00436     printf("Looping for events.\n");
00437 
00438     PLEvent* event = nsnull;
00439     
00440     while ( PR_SUCCESS == PR_Sleep( PR_MillisecondsToInterval(1)) )
00441     {
00442         rv = gEventQueue->GetEvent(&event);
00443         if (NS_FAILED(rv))
00444             return;
00445               gEventQueue->HandleEvent(event);
00446     }
00447 
00448     gEventQueue->ProcessPendingEvents(); 
00449 
00450     printf("Closing down Event Queue.\n");
00451     delete gEventQueue;
00452     gEventQueue = nsnull;
00453 
00454     printf("End looping for events.\n\n");
00455 }
00456 
00457 int
00458 main(int argc, char **argv)
00459 {
00460     int numberOfThreads = 1;
00461 
00462     if (argc > 1)
00463         numberOfThreads = atoi(argv[1]);
00464 
00465     nsCOMPtr<nsIServiceManager> servMan;
00466     NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
00467     nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
00468     NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
00469     registrar->AutoRegister(nsnull);
00470     
00471     static PRThread** threads = (PRThread**) calloc(sizeof(PRThread*), numberOfThreads);
00472     static PRThread*  aEventThread;
00473     
00474     aEventThread =   PR_CreateThread(PR_USER_THREAD,
00475                                      EventLoop,
00476                                      NULL,
00477                                      PR_PRIORITY_NORMAL,
00478                                      PR_GLOBAL_THREAD,
00479                                      PR_JOINABLE_THREAD,
00480                                      0 );
00481 
00482     
00483     PR_Sleep(PR_MillisecondsToInterval(1000));
00484 
00485     NS_ASSERTION(gEventQueue, "no main event queue"); // BAD BAD BAD.  EVENT THREAD DID NOT CREATE QUEUE.  This may be a timing issue, set the 
00486                             // sleep about longer, and try again.
00487 
00488     printf("Spawn Threads:\n");
00489     for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++)
00490     {
00491 
00492         ArgsStruct *args = (ArgsStruct *) malloc (sizeof(ArgsStruct));
00493         
00494         args->queue = gEventQueue;
00495         NS_ADDREF(args->queue);
00496         args->threadNumber = spawn;
00497 
00498         threads[spawn]  =   PR_CreateThread(PR_USER_THREAD,
00499                                             ProxyTest,
00500                                             args,
00501                                             PR_PRIORITY_NORMAL,
00502                                             PR_GLOBAL_THREAD,
00503                                             PR_JOINABLE_THREAD,
00504                                             0 );
00505 
00506         printf("\tThread (%d) spawned\n", spawn);
00507 
00508         PR_Sleep( PR_MillisecondsToInterval(250) );
00509     }
00510 
00511     printf("All Threads Spawned.\n\n");
00512     
00513    
00514     
00515    printf("Wait for threads.\n");
00516     for (PRInt32 i = 0; i < numberOfThreads; i++)
00517     {
00518         PRStatus rv;
00519         printf("Thread (%d) Join...\n", i);
00520         rv = PR_JoinThread(threads[i]);
00521         printf("Thread (%d) Joined. (error: %d).\n", i, rv);
00522     }
00523 
00524     PR_Interrupt(aEventThread);
00525     PR_JoinThread(aEventThread);
00526     
00527 
00528     printf("Calling Cleanup.\n");
00529     PR_Cleanup();
00530 
00531     printf("Return zero.\n");
00532     return 0;
00533 }