зеркало из https://github.com/mozilla/gecko-dev.git
Bug 432887 - "Add tests for XPCOM Proxies (and enable other C++ unit tests)". r=sayrer, a=Tests Only.
This commit is contained in:
Родитель
85a51c79a0
Коммит
2465d10594
|
@ -74,6 +74,7 @@ CPPSRCS = \
|
|||
TestTextFormatter.cpp \
|
||||
TestPipe.cpp \
|
||||
TestRegistrationOrder.cpp \
|
||||
TestProxies.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_ENABLE_LIBXUL
|
||||
|
@ -101,8 +102,6 @@ CPPSRCS += \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
#CPPSRCS += TimerTest.cpp
|
||||
|
||||
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
@ -125,7 +124,42 @@ ENABLE_CXX_EXCEPTIONS = 1
|
|||
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
CPP_UNIT_TESTS = TestPipe
|
||||
CPP_UNIT_TESTS = \
|
||||
TestAutoPtr \
|
||||
TestCOMPtr \
|
||||
TestCOMPtrEq \
|
||||
TestFactory \
|
||||
TestHashtables \
|
||||
TestID \
|
||||
TestObserverService \
|
||||
TestPipe \
|
||||
TestServMgr \
|
||||
TestTextFormatter \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_ENABLE_LIBXUL
|
||||
CPP_UNIT_TESTS += \
|
||||
TestArray \
|
||||
TestAutoLock \
|
||||
TestCRT \
|
||||
TestExpirationTracker \
|
||||
TestPipes \
|
||||
TestProxies \
|
||||
TestThreads \
|
||||
TestThreadPool \
|
||||
TestXPIDLString \
|
||||
TestDeque \
|
||||
TestStrings \
|
||||
TestStorageStream \
|
||||
TestTArray \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifndef MOZILLA_INTERNAL_API
|
||||
CPP_UNIT_TESTS += \
|
||||
TestStringAPI \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -156,7 +190,9 @@ check::
|
|||
@$(RUN_TEST_PROGRAM) $(FINAL_TARGET)/TestTextFormatter$(BIN_SUFFIX)
|
||||
@$(EXIT_ON_ERROR) \
|
||||
for f in $(CPP_UNIT_TESTS); do \
|
||||
echo Running $$f; \
|
||||
XPCOM_DEBUG_BREAK=stack-and-abort $(RUN_TEST_PROGRAM) $(DIST)/bin/$$f; \
|
||||
echo Finished running $$f; \
|
||||
done
|
||||
@echo "Running XPIDL tests"
|
||||
$(XPIDL_COMPILE) -m header $(srcdir)/TestScriptable.idl
|
||||
|
|
|
@ -0,0 +1,794 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Proxy Test Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ben Turner <bent.mozilla@gmail.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIThreadPool.h"
|
||||
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "prlog.h"
|
||||
|
||||
typedef nsresult(*TestFuncPtr)();
|
||||
|
||||
#define TEST_NAME "TestProxies"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* sLog = PR_NewLogModule(TEST_NAME);
|
||||
#endif
|
||||
#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
|
||||
|
||||
static nsIThread* gMainThread = nsnull;
|
||||
static nsIThread* gTestThread = nsnull;
|
||||
|
||||
static nsresult
|
||||
GetProxyForObject(nsIEventTarget* aTarget,
|
||||
REFNSIID aIID,
|
||||
nsISupports* aObj,
|
||||
PRInt32 aProxyType,
|
||||
void** aProxyObject)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIProxyObjectManager> proxyObjMgr =
|
||||
do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return proxyObjMgr->GetProxyForObject(aTarget, aIID, aObj, aProxyType,
|
||||
aProxyObject);
|
||||
}
|
||||
|
||||
class nsAutoTestThread
|
||||
{
|
||||
public:
|
||||
nsAutoTestThread(nsIThread** aGlobal = nsnull)
|
||||
: mGlobal(aGlobal)
|
||||
{
|
||||
nsCOMPtr<nsIThread> newThread;
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(newThread));
|
||||
NS_ENSURE_SUCCESS(rv,);
|
||||
|
||||
rv = newThread->GetPRThread(&mNativeThread);
|
||||
NS_ENSURE_SUCCESS(rv,);
|
||||
|
||||
LOG(("Created test thread [0x%p]", static_cast<void*>(mNativeThread)));
|
||||
|
||||
newThread.swap(mThread);
|
||||
|
||||
if (mGlobal)
|
||||
*mGlobal = mThread;
|
||||
}
|
||||
|
||||
~nsAutoTestThread()
|
||||
{
|
||||
if (mGlobal)
|
||||
*mGlobal = nsnull;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
void* nativeThread = static_cast<void*>(mNativeThread);
|
||||
#endif
|
||||
|
||||
LOG(("Shutting down test thread [0x%p]", nativeThread));
|
||||
mThread->Shutdown();
|
||||
LOG(("Test thread successfully shut down [0x%p]", nativeThread));
|
||||
}
|
||||
|
||||
operator nsDerivedSafe<nsIThread>*() const
|
||||
{
|
||||
return mThread;
|
||||
}
|
||||
|
||||
nsDerivedSafe<nsIThread>* operator->() const
|
||||
{
|
||||
return mThread;
|
||||
}
|
||||
|
||||
private:
|
||||
nsIThread** mGlobal;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
PRThread* mNativeThread;
|
||||
};
|
||||
|
||||
class SimpleRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SimpleRunnable(const char* aType = "SimpleRunnable")
|
||||
: mType(aType)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
LOG(("%s::Run() [0x%p]", mType,
|
||||
static_cast<void*>(static_cast<nsISupports*>(this))));
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
const char* mType;
|
||||
};
|
||||
|
||||
class TestTargetThreadRunnable : public SimpleRunnable
|
||||
{
|
||||
public:
|
||||
TestTargetThreadRunnable(nsIThread* aTarget)
|
||||
: SimpleRunnable("TestTargetThreadRunnable"),
|
||||
mTarget(aTarget)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsresult rv = SimpleRunnable::Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
|
||||
if (currentThread != mTarget) {
|
||||
NS_ERROR("Proxy sent call to wrong thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIThread> mTarget;
|
||||
};
|
||||
|
||||
class ChainedProxyRunnable : public SimpleRunnable
|
||||
{
|
||||
public:
|
||||
ChainedProxyRunnable(nsIThread* aSecondTarget,
|
||||
nsIThread* aThirdTarget = nsnull)
|
||||
: SimpleRunnable("ChainedProxyRunnable"), mSecondTarget(aSecondTarget),
|
||||
mThirdTarget(aThirdTarget)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsresult rv = SimpleRunnable::Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<SimpleRunnable> runnable = mThirdTarget ?
|
||||
new ChainedProxyRunnable(mThirdTarget) :
|
||||
new SimpleRunnable();
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy;
|
||||
rv = GetProxyForObject(mSecondTarget, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIThread> mSecondTarget;
|
||||
nsCOMPtr<nsIThread> mThirdTarget;
|
||||
};
|
||||
|
||||
class IncrementingRunnable : public SimpleRunnable
|
||||
{
|
||||
public:
|
||||
IncrementingRunnable(PRUint32* aCounter, PRLock* aLock = nsnull)
|
||||
: SimpleRunnable("IncrementingRunnable"), mCounter(aCounter), mLock(aLock)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsresult rv = SimpleRunnable::Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mLock)
|
||||
PR_Lock(mLock);
|
||||
|
||||
(*mCounter)++;
|
||||
|
||||
if (mLock)
|
||||
PR_Unlock(mLock);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
PRUint32* mCounter;
|
||||
PRLock* mLock;
|
||||
};
|
||||
|
||||
class NonThreadsafeRunnable : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NonThreadsafeRunnable(PRUint32* aCounter,
|
||||
const char* aType = "NonThreadsafeRunnable")
|
||||
: mCounter(aCounter),
|
||||
mType(aType)
|
||||
{ }
|
||||
|
||||
virtual ~NonThreadsafeRunnable()
|
||||
{ };
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
LOG(("%s::Run() [0x%p]", mType,
|
||||
static_cast<void*>(static_cast<nsISupports*>(this))));
|
||||
|
||||
(*mCounter)++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
PRUint32* mCounter;
|
||||
const char* mType;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(NonThreadsafeRunnable, nsIRunnable)
|
||||
|
||||
class MainThreadRunnable : public NonThreadsafeRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
MainThreadRunnable(PRUint32* aCounter)
|
||||
: NonThreadsafeRunnable(aCounter, "MainThreadRunnable")
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_ERROR("Not running on the main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~MainThreadRunnable()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_ERROR("Not running on the main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_ERROR("Not running on the main thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = NonThreadsafeRunnable::Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(MainThreadRunnable, NonThreadsafeRunnable)
|
||||
|
||||
class ProxyGetter : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ProxyGetter(nsIRunnable* aRunnable, nsIRunnable** retval)
|
||||
: mRunnable(aRunnable), _retval(retval)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
*_retval = nsnull;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
NS_ERROR("Shouldn't be running on the main thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy;
|
||||
nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
|
||||
mRunnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
proxy.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsIRunnable* mRunnable;
|
||||
nsIRunnable** _retval;
|
||||
};
|
||||
|
||||
class RunnableGetter : public nsRunnable
|
||||
{
|
||||
public:
|
||||
RunnableGetter(PRUint32* aCounter, nsIRunnable** retval)
|
||||
: mCounter(aCounter), _retval(retval)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
*_retval = nsnull;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
NS_ERROR("Shouldn't be running on the main thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable = new NonThreadsafeRunnable(mCounter);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
runnable.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
PRUint32* mCounter;
|
||||
nsIRunnable** _retval;
|
||||
};
|
||||
|
||||
nsresult
|
||||
TestTargetThread()
|
||||
{
|
||||
LOG(("--- Running TestTargetThread ---"));
|
||||
|
||||
nsRefPtr<TestTargetThreadRunnable> runnable =
|
||||
new TestTargetThreadRunnable(gMainThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy;
|
||||
nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = new TestTargetThreadRunnable(gTestThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TestNonThreadsafeProxy()
|
||||
{
|
||||
LOG(("--- Running TestNonThreadsafeProxy 1 ---"));
|
||||
|
||||
// Make sure a non-threadsafe object and proxy to it (both created on the same
|
||||
// thread) can be used on the same thread.
|
||||
|
||||
PRUint32 counter = 0;
|
||||
nsCOMPtr<nsIRunnable> runnable(new MainThreadRunnable(&counter));
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy;
|
||||
nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 otherCounter = 0; otherCounter < 5;) {
|
||||
rv = gTestThread->Dispatch(proxy, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Make sure a non-threadsafe object and proxy to it (both created on the same
|
||||
// thread) can be used on a different thread.
|
||||
|
||||
LOG(("--- Running TestNonThreadsafeProxy 2 ---"));
|
||||
|
||||
counter = 0;
|
||||
runnable = new NonThreadsafeRunnable(&counter);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = nsnull;
|
||||
|
||||
for (PRUint32 otherCounter = 0; otherCounter < 5;) {
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(counter == 5, NS_ERROR_FAILURE);
|
||||
|
||||
// Make sure a non-threadsafe object and proxy to it (created on different
|
||||
// threads) can be used by any thread.
|
||||
|
||||
LOG(("--- Running TestNonThreadsafeProxy 3 ---"));
|
||||
|
||||
counter = 0;
|
||||
proxy = nsnull;
|
||||
|
||||
runnable = new MainThreadRunnable(&counter);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxyGetter =
|
||||
new ProxyGetter(runnable, getter_AddRefs(proxy));
|
||||
NS_ENSURE_TRUE(proxyGetter, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = gTestThread->Dispatch(proxyGetter, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(proxy, NS_ERROR_FAILURE);
|
||||
|
||||
for (PRUint32 otherCounter = 0; otherCounter < 5;) {
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Make sure a non-threadsafe object (created on thread 1) and proxy to it
|
||||
// (created on thread 2) can be used by thread 3.
|
||||
|
||||
LOG(("--- Running TestNonThreadsafeProxy 4 ---"));
|
||||
|
||||
counter = 0;
|
||||
proxy = nsnull;
|
||||
runnable = nsnull;
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnableGetter =
|
||||
new RunnableGetter(&counter, getter_AddRefs(runnable));
|
||||
NS_ENSURE_TRUE(runnableGetter, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = gTestThread->Dispatch(runnableGetter, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE);
|
||||
|
||||
proxyGetter = new ProxyGetter(runnable, getter_AddRefs(proxy));
|
||||
NS_ENSURE_TRUE(proxyGetter, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsAutoTestThread otherTestThread;
|
||||
NS_ENSURE_TRUE(otherTestThread, NS_ERROR_FAILURE);
|
||||
|
||||
rv = otherTestThread->Dispatch(proxyGetter, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(proxy, NS_ERROR_FAILURE);
|
||||
|
||||
for (PRUint32 otherCounter = 0; otherCounter < 5;) {
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TestChainedProxy()
|
||||
{
|
||||
LOG(("--- Running TestChainedProxy ---"));
|
||||
|
||||
nsRefPtr<ChainedProxyRunnable> runnable =
|
||||
new ChainedProxyRunnable(gMainThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy;
|
||||
nsresult rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This will do a test->main call
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = new ChainedProxyRunnable(gTestThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This will do a main->test call
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = new ChainedProxyRunnable(gMainThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This will do a main->main call
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = new ChainedProxyRunnable(gTestThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This will do a test->test call
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = new ChainedProxyRunnable(gMainThread, gTestThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This will do a test->main->test call
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TestReleaseOfRealObjects()
|
||||
{
|
||||
LOG(("--- Running TestReleaseOfRealObjects ---"));
|
||||
|
||||
PRUint32 counter = 0, otherCounter = 0;
|
||||
|
||||
nsRefPtr<IncrementingRunnable> runnable(new IncrementingRunnable(&counter));
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy1;
|
||||
nsresult rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy1));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy2;
|
||||
rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy2));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy3;
|
||||
rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy3));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_FALSE(proxy1 == proxy2, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(proxy2 == proxy3, NS_ERROR_FAILURE);
|
||||
proxy3 = nsnull;
|
||||
|
||||
rv = proxy1->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
rv = proxy2->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
runnable = nsnull;
|
||||
|
||||
rv = proxy1->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
rv = proxy2->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
proxy1 = nsnull;
|
||||
|
||||
rv = proxy2->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TestCurrentThreadProxy()
|
||||
{
|
||||
LOG(("--- Running TestCurrentThreadProxy ---"));
|
||||
|
||||
PRUint32 counter = 0, otherCounter = 0;
|
||||
nsRefPtr<IncrementingRunnable> runnable(new IncrementingRunnable(&counter));
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy1;
|
||||
nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_SYNC,
|
||||
getter_AddRefs(proxy1));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy2;
|
||||
rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_SYNC | NS_PROXY_ALWAYS,
|
||||
getter_AddRefs(proxy2));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_FALSE(proxy1 == proxy2, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIRunnable> realRunnable(do_QueryInterface(runnable));
|
||||
NS_ENSURE_TRUE(realRunnable, NS_ERROR_FAILURE);
|
||||
|
||||
NS_ENSURE_TRUE(static_cast<void*>(realRunnable) == static_cast<void*>(runnable),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
rv = proxy1->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
rv = proxy2->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TestAsyncProxy()
|
||||
{
|
||||
LOG(("--- Running TestAsyncProxy ---"));
|
||||
|
||||
// Test async proxies to the current thread.
|
||||
|
||||
PRUint32 counter = 0;
|
||||
nsRefPtr<SimpleRunnable> runnable(new IncrementingRunnable(&counter));
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRunnable> proxy;
|
||||
nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_ASYNC,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
runnable = nsnull;
|
||||
|
||||
for (PRUint32 i = 0; i < 5; i++) {
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
while (counter < 5) {
|
||||
rv = NS_ProcessPendingEvents(gMainThread, PR_SecondsToInterval(1));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Now test async proxies to another thread.
|
||||
|
||||
PRLock* counterLock = nsAutoLock::NewLock("counterLock");
|
||||
NS_ENSURE_TRUE(counterLock, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
counter = 0;
|
||||
runnable = new IncrementingRunnable(&counter, counterLock);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable,
|
||||
NS_PROXY_ASYNC, getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < 5; i++) {
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
PRUint32 safeCounter = 0;
|
||||
while (safeCounter < 5) {
|
||||
rv = NS_ProcessPendingEvents(gMainThread, PR_SecondsToInterval(1));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoLock lock(counterLock);
|
||||
safeCounter = counter;
|
||||
}
|
||||
|
||||
nsAutoLock::DestroyLock(counterLock);
|
||||
|
||||
// Now test async proxies to another thread that create sync proxies to this
|
||||
// thread.
|
||||
|
||||
runnable = new ChainedProxyRunnable(gMainThread);
|
||||
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable),
|
||||
runnable, NS_PROXY_ASYNC,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = proxy->Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// That was async, so make sure to wait for all the events on the test thread
|
||||
// to be processed before we return. This is easy to do with an empty sync
|
||||
// event.
|
||||
nsCOMPtr<nsIRunnable> flusher = new nsRunnable();
|
||||
NS_ENSURE_TRUE(flusher, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
LOG(("Flushing events on test thread"));
|
||||
|
||||
rv = gTestThread->Dispatch(flusher, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG(("Flushing events completed"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ScopedXPCOM xpcom(TEST_NAME);
|
||||
NS_ENSURE_FALSE(xpcom.failed(), 1);
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
|
||||
NS_ENSURE_TRUE(mainThread, 1);
|
||||
|
||||
LOG(("Got main thread"));
|
||||
gMainThread = mainThread;
|
||||
|
||||
nsAutoTestThread testThread(&gTestThread);
|
||||
NS_ENSURE_TRUE(testThread, 1);
|
||||
|
||||
static TestFuncPtr testsToRun[] = {
|
||||
TestTargetThread,
|
||||
// TestNonThreadsafeProxy, /* Not currently supported! */
|
||||
TestChainedProxy,
|
||||
TestReleaseOfRealObjects,
|
||||
TestCurrentThreadProxy,
|
||||
TestAsyncProxy
|
||||
};
|
||||
static PRUint32 testCount = sizeof(testsToRun) / sizeof(testsToRun[0]);
|
||||
|
||||
for (PRUint32 i = 0; i < testCount; i++) {
|
||||
nsresult rv = testsToRun[i]();
|
||||
NS_ENSURE_SUCCESS(rv, 1);
|
||||
}
|
||||
|
||||
LOG(("--- Finished all tests ---"));
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче