From 2ab76ffdb101f9ce880e82bb1a54baf52a3bb045 Mon Sep 17 00:00:00 2001 From: "warren%netscape.com" Date: Sat, 29 Aug 1998 01:51:44 +0000 Subject: [PATCH] Added test for service manager. git-svn-id: svn://10.0.0.236/trunk@8778 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/tests/TestServMgr.cpp | 220 +++++++++++++++++++++ mozilla/xpcom/tests/makefile.win | 10 +- mozilla/xpcom/tests/services/MyService.cpp | 168 ++++++++++++++++ mozilla/xpcom/tests/services/MyService.h | 48 +++++ mozilla/xpcom/tests/services/makefile.win | 49 +++++ 5 files changed, 491 insertions(+), 4 deletions(-) create mode 100644 mozilla/xpcom/tests/TestServMgr.cpp create mode 100644 mozilla/xpcom/tests/services/MyService.cpp create mode 100644 mozilla/xpcom/tests/services/MyService.h create mode 100644 mozilla/xpcom/tests/services/makefile.win diff --git a/mozilla/xpcom/tests/TestServMgr.cpp b/mozilla/xpcom/tests/TestServMgr.cpp new file mode 100644 index 00000000000..c8ca678ec47 --- /dev/null +++ b/mozilla/xpcom/tests/TestServMgr.cpp @@ -0,0 +1,220 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "MyService.h" +#include "nsIServiceManager.h" +#include + +static NS_DEFINE_IID(kIMyServiceCID, NS_IMYSERVICE_CID); +static NS_DEFINE_IID(kIMyServiceIID, NS_IMYSERVICE_IID); + +//////////////////////////////////////////////////////////////////////////////// + +IMyService* myServ = NULL; + +nsresult +BeginTest(int testNumber, nsIShutdownListener* listener) +{ + nsresult err; + NS_ASSERTION(myServ == NULL, "myServ not reset"); + err = NSServiceManager::GetService(kIMyServiceCID, kIMyServiceIID, + (nsISupports**)&myServ, listener); + return err; +} + +nsresult +EndTest(int testNumber, nsIShutdownListener* listener) +{ + nsresult err = NS_OK; + + if (myServ) { + err = myServ->Doit(); + if (err != NS_OK) return err; + + err = NSServiceManager::ReleaseService(kIMyServiceCID, myServ, listener); + if (err != NS_OK) return err; + myServ = NULL; + } + + printf("test %d succeeded\n", testNumber); + return NS_OK; +} + +nsresult +SimpleTest(int testNumber) +{ + // This test just gets a service, uses it and releases it. + + nsresult err; + err = BeginTest(testNumber, NULL); + if (err != NS_OK) return err; + err = EndTest(testNumber, NULL); + return err; +} + +//////////////////////////////////////////////////////////////////////////////// + +class HandleMyServiceShutdown : public nsIShutdownListener { +public: + + NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service); + + HandleMyServiceShutdown(void) { NS_INIT_REFCNT(); } + virtual ~HandleMyServiceShutdown(void) {} + + NS_DECL_ISUPPORTS +}; + +static NS_DEFINE_IID(kIShutdownListenerIID, NS_ISHUTDOWNLISTENER_IID); +NS_IMPL_ISUPPORTS(HandleMyServiceShutdown, kIShutdownListenerIID); + +nsresult +HandleMyServiceShutdown::OnShutdown(const nsCID& cid, nsISupports* service) +{ + if (cid.Equals(kIMyServiceCID)) { + NS_ASSERTION(service == myServ, "wrong service!"); + nsrefcnt cnt = myServ->Release(); + myServ = NULL; + } + return NS_OK; +} + +nsresult +AsyncShutdown(int testNumber) +{ + nsresult err; + + // If the AsyncShutdown was truly asynchronous and happened on another + // thread, we'd have to protect all accesses to myServ throughout this + // code with a monitor. + + err = NSServiceManager::ShutdownService(kIMyServiceCID); + if (err == NS_ERROR_SERVICE_IN_USE) { + printf("async shutdown -- service still in use\n"); + return NS_OK; + } + if (err == NS_ERROR_SERVICE_NOT_FOUND) { + printf("async shutdown -- service not found\n"); + return NS_OK; + } + return err; +} + +nsresult +AsyncShutdownTest(int testNumber) +{ + // This test gets a service, but then gets an async request for + // shutdown before it gets a chance to use it. This causes the myServ + // variable to become NULL and EndTest to do nothing. The async request + // will actually unload the DLL in this test. + + nsresult err; + HandleMyServiceShutdown* listener = new HandleMyServiceShutdown(); + listener->AddRef(); + + err = BeginTest(testNumber, listener); + if (err != NS_OK) return err; + err = AsyncShutdown(testNumber); + if (err != NS_OK) return err; + err = EndTest(testNumber, listener); + + nsrefcnt cnt = listener->Release(); + NS_ASSERTION(cnt == 0, "failed to release listener"); + return err; +} + +nsresult +AsyncNoShutdownTest(int testNumber) +{ + // This test gets a service, and also gets an async request for shutdown, + // but the service doesn't get shut down because some other client (who's + // not participating in the async shutdown game as he should) is + // continuing to hang onto the service. This causes myServ variable to + // get set to NULL, but the service doesn't get unloaded right away as + // it should. + + nsresult err; + HandleMyServiceShutdown* listener = new HandleMyServiceShutdown(); + listener->AddRef(); + + err = BeginTest(testNumber, listener); + if (err != NS_OK) return err; + + // Create some other user of kIMyServiceCID, preventing it from + // really going away: + IMyService* otherClient; + err = NSServiceManager::GetService(kIMyServiceCID, kIMyServiceIID, + (nsISupports**)&otherClient); + if (err != NS_OK) return err; + + err = AsyncShutdown(testNumber); + if (err != NS_OK) return err; + err = EndTest(testNumber, listener); + + // Finally, release the other client. + err = NSServiceManager::ReleaseService(kIMyServiceCID, otherClient); + if (err != NS_OK) return err; + + nsrefcnt cnt = listener->Release(); + NS_ASSERTION(cnt == 0, "failed to release listener"); + return err; +} + +//////////////////////////////////////////////////////////////////////////////// + +void +SetupFactories(void) +{ + nsresult err; + // seed the repository (hack) + err = NSRepository::RegisterFactory(kIMyServiceCID, "MyService.dll", + PR_TRUE, PR_FALSE); + NS_ASSERTION(err == NS_OK, "failed to register my factory"); +} + +int +main(void) +{ + nsresult err; + int testNumber = 0; + + SetupFactories(); + + err = SimpleTest(++testNumber); + if (err != NS_OK) + goto error; + + err = AsyncShutdownTest(++testNumber); + if (err != NS_OK) + goto error; + + err = AsyncNoShutdownTest(++testNumber); + if (err != NS_OK) + goto error; + + AsyncShutdown(++testNumber); + + printf("there was great success\n"); + return 0; + + error: + printf("test %d failed\n", testNumber); + return -1; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/tests/makefile.win b/mozilla/xpcom/tests/makefile.win index ae17ba1bab9..329eb8c1912 100644 --- a/mozilla/xpcom/tests/makefile.win +++ b/mozilla/xpcom/tests/makefile.win @@ -19,20 +19,21 @@ DEPTH=..\.. IGNORE_MANIFEST=1 -DIRS = dynamic windows +DIRS = dynamic windows services MAKE_OBJ_TYPE = EXE PROG1 = .\$(OBJDIR)\TestFactory.exe PROG2 = .\$(OBJDIR)\RegFactory.exe PROG3 = .\$(OBJDIR)\TestArray.exe PROG4 = .\$(OBJDIR)\TestID.exe -PROGRAMS = $(PROG1) $(PROG2) $(PROG3) $(PROG4) +PROG5 = .\$(OBJDIR)\TestServMgr.exe +PROGRAMS = $(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) LCFLAGS=-DUSE_NSREG REQUIRES=libreg -LINCS=-I..\src +LINCS=-I..\src -Iservices LLIBS= \ $(DIST)\lib\xpcom32.lib \ @@ -69,5 +70,6 @@ clobber:: $(PROG1): $(OBJDIR) TestFactory.cpp $(PROG2): $(OBJDIR) RegFactory.cpp $(PROG3): $(OBJDIR) TestArray.cpp -$(PROG3): $(OBJDIR) TestID.cpp +$(PROG4): $(OBJDIR) TestID.cpp +$(PROG5): $(OBJDIR) TestServMgr.cpp diff --git a/mozilla/xpcom/tests/services/MyService.cpp b/mozilla/xpcom/tests/services/MyService.cpp new file mode 100644 index 00000000000..3fd73c02a08 --- /dev/null +++ b/mozilla/xpcom/tests/services/MyService.cpp @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "MyService.h" +#include "nsIServiceManager.h" +#include + +//////////////////////////////////////////////////////////////////////////////// + +class MyService : public IMyService { +public: + + NS_IMETHOD + Doit(void); + + MyService(nsISupports* outer); + virtual ~MyService(void); + + NS_DECL_ISUPPORTS + +}; + +//////////////////////////////////////////////////////////////////////////////// + +class MyServiceFactory : public nsIFactory { +public: + + NS_DECL_ISUPPORTS + + // nsIFactory methods: + + NS_IMETHOD CreateInstance(nsISupports *aOuter, + REFNSIID aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + + // MyService methods: + + MyServiceFactory(void); + virtual ~MyServiceFactory(void); + + PRBool CanUnload(void) { return mOutstandingInstances == 0; } + + friend MyService; + +protected: + PRBool mStarted; + PRUint32 mOutstandingInstances; +}; + +MyServiceFactory* gFact = NULL; + +//////////////////////////////////////////////////////////////////////////////// +// MyService Implementation + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIMyServiceIID, NS_IMYSERVICE_IID); +NS_IMPL_ISUPPORTS(MyService, kIMyServiceIID); + +MyService::MyService(nsISupports* outer) +{ + NS_INIT_REFCNT(outer); + // incrementing this will keep our factory from getting unloaded + gFact->mOutstandingInstances++; + printf(" creating my service\n"); +} + +MyService::~MyService(void) +{ + // decrementing this will allow our factory to get unloaded + --gFact->mOutstandingInstances; + printf(" destroying my service\n"); +} + +nsresult +MyService::Doit(void) +{ + printf(" invoking my service\n"); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// MyServiceFactory Implementation + +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); +NS_IMPL_ISUPPORTS(MyServiceFactory, kIFactoryIID); + +MyServiceFactory::MyServiceFactory(void) + : mStarted(PR_FALSE), mOutstandingInstances(0) +{ + NS_INIT_REFCNT(); + printf("initializing my service factory\n"); +} + +MyServiceFactory::~MyServiceFactory(void) +{ + NS_ASSERTION(mOutstandingInstances == 0, "unloading factory when there are still instances"); + printf("finalizing my service factory\n"); +} + +nsresult +MyServiceFactory::CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + MyService* serv = new MyService(aOuter); + if (serv == NULL) + return NS_ERROR_OUT_OF_MEMORY; + return serv->QueryInterface(aIID, aResult); +} + +nsresult +MyServiceFactory::LockFactory(PRBool aLock) +{ + mOutstandingInstances += aLock ? 1 : -1; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// DLL Entry Points: + +static NS_DEFINE_IID(kIMyServiceCID, NS_IMYSERVICE_CID); + +extern "C" NS_EXPORT nsresult +NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) +{ + if (!aClass.Equals(kIMyServiceCID)) + return NS_ERROR_FACTORY_NOT_REGISTERED; + if (gFact == NULL) { + printf("loading my service factory\n"); + gFact = new MyServiceFactory(); + if (gFact == NULL) + return NS_ERROR_OUT_OF_MEMORY; + gFact->AddRef(); // one for our global + } + gFact->AddRef(); // one for the client + *aFactory = gFact; + return NS_OK; +} + +extern "C" NS_EXPORT PRBool +NSCanUnload(void) +{ + if (gFact && gFact->CanUnload()) { + nsrefcnt cnt = gFact->Release(); + NS_ASSERTION(cnt == 0, "can't release service factory"); + gFact = NULL; + printf("unloading my service factory\n"); + return PR_TRUE; + } + return PR_FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/tests/services/MyService.h b/mozilla/xpcom/tests/services/MyService.h new file mode 100644 index 00000000000..0b7dde6fac2 --- /dev/null +++ b/mozilla/xpcom/tests/services/MyService.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef MyService_h__ +#define MyService_h__ + +#include "nsISupports.h" + +class IMyService : public nsISupports { +public: + + NS_IMETHOD + Doit(void) = 0; + +}; + +#define NS_IMYSERVICE_IID \ +{ /* fedc3380-3648-11d2-8163-006008119d7a */ \ + 0xfedc3380, \ + 0x3648, \ + 0x11d2, \ + {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +#define NS_IMYSERVICE_CID \ +{ /* 34876550-364b-11d2-8163-006008119d7a */ \ + 0x34876550, \ + 0x364b, \ + 0x11d2, \ + {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +#endif // MyService_h__ diff --git a/mozilla/xpcom/tests/services/makefile.win b/mozilla/xpcom/tests/services/makefile.win new file mode 100644 index 00000000000..03a3ec808dc --- /dev/null +++ b/mozilla/xpcom/tests/services/makefile.win @@ -0,0 +1,49 @@ +#!nmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH=..\..\.. + +IGNORE_MANIFEST=1 + +MAKE_OBJ_TYPE = DLL + +DLL = $(OBJDIR)\MyService.dll + +LINCS = -I.. -I../../src + +LLIBS= \ + $(DIST)\lib\xpcom32.lib \ + $(LIBNSPR) \ + $(DIST)\lib\libplc21.lib +!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE) +LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib +!endif + +CPPSRCS = \ + MyService.cpp \ + $(NULL) + +CPP_OBJS = \ + .\$(OBJDIR)\MyService.obj \ + $(NULL) + +MODULE = xpcom + +include <$(DEPTH)\config\rules.mak> + +install:: $(DLL) + $(MAKE_INSTALL) $(DLL) $(DIST)\bin