xpcom/tests/TestRacingServiceManager.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "TestHarness.h"
michael@0 7
michael@0 8 #include "nsIFactory.h"
michael@0 9 #include "mozilla/Module.h"
michael@0 10 #include "nsXULAppAPI.h"
michael@0 11 #include "nsIThread.h"
michael@0 12 #include "nsIComponentRegistrar.h"
michael@0 13
michael@0 14 #include "nsAutoPtr.h"
michael@0 15 #include "nsThreadUtils.h"
michael@0 16 #include "nsXPCOMCIDInternal.h"
michael@0 17 #include "pratom.h"
michael@0 18 #include "prmon.h"
michael@0 19 #include "mozilla/Attributes.h"
michael@0 20
michael@0 21 #include "mozilla/ReentrantMonitor.h"
michael@0 22 using namespace mozilla;
michael@0 23
michael@0 24 #ifdef DEBUG
michael@0 25 #define TEST_ASSERTION(_test, _msg) \
michael@0 26 NS_ASSERTION(_test, _msg);
michael@0 27 #else
michael@0 28 #define TEST_ASSERTION(_test, _msg) \
michael@0 29 PR_BEGIN_MACRO \
michael@0 30 if (!(_test)) { \
michael@0 31 NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_test, __FILE__, __LINE__); \
michael@0 32 } \
michael@0 33 PR_END_MACRO
michael@0 34 #endif
michael@0 35
michael@0 36 /* f93f6bdc-88af-42d7-9d64-1b43c649a3e5 */
michael@0 37 #define FACTORY_CID1 \
michael@0 38 { \
michael@0 39 0xf93f6bdc, \
michael@0 40 0x88af, \
michael@0 41 0x42d7, \
michael@0 42 { 0x9d, 0x64, 0x1b, 0x43, 0xc6, 0x49, 0xa3, 0xe5 } \
michael@0 43 }
michael@0 44 NS_DEFINE_CID(kFactoryCID1, FACTORY_CID1);
michael@0 45
michael@0 46 /* ef38ad65-6595-49f0-8048-e819f81d15e2 */
michael@0 47 #define FACTORY_CID2 \
michael@0 48 { \
michael@0 49 0xef38ad65, \
michael@0 50 0x6595, \
michael@0 51 0x49f0, \
michael@0 52 { 0x80, 0x48, 0xe8, 0x19, 0xf8, 0x1d, 0x15, 0xe2 } \
michael@0 53 }
michael@0 54 NS_DEFINE_CID(kFactoryCID2, FACTORY_CID2);
michael@0 55
michael@0 56 #define FACTORY_CONTRACTID \
michael@0 57 "TestRacingThreadManager/factory;1"
michael@0 58
michael@0 59 int32_t gComponent1Count = 0;
michael@0 60 int32_t gComponent2Count = 0;
michael@0 61
michael@0 62 ReentrantMonitor* gReentrantMonitor = nullptr;
michael@0 63
michael@0 64 bool gCreateInstanceCalled = false;
michael@0 65 bool gMainThreadWaiting = false;
michael@0 66
michael@0 67 class AutoCreateAndDestroyReentrantMonitor
michael@0 68 {
michael@0 69 public:
michael@0 70 AutoCreateAndDestroyReentrantMonitor(ReentrantMonitor** aReentrantMonitorPtr)
michael@0 71 : mReentrantMonitorPtr(aReentrantMonitorPtr) {
michael@0 72 *aReentrantMonitorPtr =
michael@0 73 new ReentrantMonitor("TestRacingServiceManager::AutoMon");
michael@0 74 TEST_ASSERTION(*aReentrantMonitorPtr, "Out of memory!");
michael@0 75 }
michael@0 76
michael@0 77 ~AutoCreateAndDestroyReentrantMonitor() {
michael@0 78 if (*mReentrantMonitorPtr) {
michael@0 79 delete *mReentrantMonitorPtr;
michael@0 80 *mReentrantMonitorPtr = nullptr;
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 private:
michael@0 85 ReentrantMonitor** mReentrantMonitorPtr;
michael@0 86 };
michael@0 87
michael@0 88 class Factory MOZ_FINAL : public nsIFactory
michael@0 89 {
michael@0 90 public:
michael@0 91 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 92
michael@0 93 Factory() : mFirstComponentCreated(false) { }
michael@0 94
michael@0 95 NS_IMETHOD CreateInstance(nsISupports* aDelegate,
michael@0 96 const nsIID& aIID,
michael@0 97 void** aResult);
michael@0 98
michael@0 99 NS_IMETHOD LockFactory(bool aLock) {
michael@0 100 return NS_OK;
michael@0 101 }
michael@0 102
michael@0 103 bool mFirstComponentCreated;
michael@0 104 };
michael@0 105
michael@0 106 NS_IMPL_ISUPPORTS(Factory, nsIFactory)
michael@0 107
michael@0 108 class Component1 MOZ_FINAL : public nsISupports
michael@0 109 {
michael@0 110 public:
michael@0 111 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 112
michael@0 113 Component1() {
michael@0 114 // This is the real test - make sure that only one instance is ever created.
michael@0 115 int32_t count = PR_AtomicIncrement(&gComponent1Count);
michael@0 116 TEST_ASSERTION(count == 1, "Too many components created!");
michael@0 117 }
michael@0 118 };
michael@0 119
michael@0 120 NS_IMPL_ADDREF(Component1)
michael@0 121 NS_IMPL_RELEASE(Component1)
michael@0 122
michael@0 123 NS_INTERFACE_MAP_BEGIN(Component1)
michael@0 124 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 125 NS_INTERFACE_MAP_END
michael@0 126
michael@0 127 class Component2 MOZ_FINAL : public nsISupports
michael@0 128 {
michael@0 129 public:
michael@0 130 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 131
michael@0 132 Component2() {
michael@0 133 // This is the real test - make sure that only one instance is ever created.
michael@0 134 int32_t count = PR_AtomicIncrement(&gComponent2Count);
michael@0 135 TEST_ASSERTION(count == 1, "Too many components created!");
michael@0 136 }
michael@0 137 };
michael@0 138
michael@0 139 NS_IMPL_ADDREF(Component2)
michael@0 140 NS_IMPL_RELEASE(Component2)
michael@0 141
michael@0 142 NS_INTERFACE_MAP_BEGIN(Component2)
michael@0 143 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 144 NS_INTERFACE_MAP_END
michael@0 145
michael@0 146 NS_IMETHODIMP
michael@0 147 Factory::CreateInstance(nsISupports* aDelegate,
michael@0 148 const nsIID& aIID,
michael@0 149 void** aResult)
michael@0 150 {
michael@0 151 // Make sure that the second thread beat the main thread to the getService
michael@0 152 // call.
michael@0 153 TEST_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
michael@0 154
michael@0 155 {
michael@0 156 ReentrantMonitorAutoEnter mon(*gReentrantMonitor);
michael@0 157
michael@0 158 gCreateInstanceCalled = true;
michael@0 159 mon.Notify();
michael@0 160
michael@0 161 mon.Wait(PR_MillisecondsToInterval(3000));
michael@0 162 }
michael@0 163
michael@0 164 NS_ENSURE_FALSE(aDelegate, NS_ERROR_NO_AGGREGATION);
michael@0 165 NS_ENSURE_ARG_POINTER(aResult);
michael@0 166
michael@0 167 nsCOMPtr<nsISupports> instance;
michael@0 168
michael@0 169 if (!mFirstComponentCreated) {
michael@0 170 instance = new Component1();
michael@0 171 }
michael@0 172 else {
michael@0 173 instance = new Component2();
michael@0 174 }
michael@0 175 NS_ENSURE_TRUE(instance, NS_ERROR_OUT_OF_MEMORY);
michael@0 176
michael@0 177 nsresult rv = instance->QueryInterface(aIID, aResult);
michael@0 178 NS_ENSURE_SUCCESS(rv, rv);
michael@0 179
michael@0 180 return NS_OK;
michael@0 181 }
michael@0 182
michael@0 183 class Runnable : public nsRunnable
michael@0 184 {
michael@0 185 public:
michael@0 186 NS_DECL_NSIRUNNABLE
michael@0 187
michael@0 188 Runnable() : mFirstRunnableDone(false) { }
michael@0 189
michael@0 190 bool mFirstRunnableDone;
michael@0 191 };
michael@0 192
michael@0 193 NS_IMETHODIMP
michael@0 194 Runnable::Run()
michael@0 195 {
michael@0 196 {
michael@0 197 ReentrantMonitorAutoEnter mon(*gReentrantMonitor);
michael@0 198
michael@0 199 while (!gMainThreadWaiting) {
michael@0 200 mon.Wait();
michael@0 201 }
michael@0 202 }
michael@0 203
michael@0 204 nsresult rv;
michael@0 205 nsCOMPtr<nsISupports> component;
michael@0 206
michael@0 207 if (!mFirstRunnableDone) {
michael@0 208 component = do_GetService(kFactoryCID1, &rv);
michael@0 209 }
michael@0 210 else {
michael@0 211 component = do_GetService(FACTORY_CONTRACTID, &rv);
michael@0 212 }
michael@0 213 TEST_ASSERTION(NS_SUCCEEDED(rv), "GetService failed!");
michael@0 214
michael@0 215 return NS_OK;
michael@0 216 }
michael@0 217
michael@0 218 static Factory* gFactory;
michael@0 219
michael@0 220 static already_AddRefed<nsIFactory>
michael@0 221 CreateFactory(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
michael@0 222 {
michael@0 223 if (!gFactory) {
michael@0 224 gFactory = new Factory();
michael@0 225 NS_ADDREF(gFactory);
michael@0 226 }
michael@0 227 nsCOMPtr<nsIFactory> ret = gFactory;
michael@0 228 return ret.forget();
michael@0 229 }
michael@0 230
michael@0 231 static const mozilla::Module::CIDEntry kLocalCIDs[] = {
michael@0 232 { &kFactoryCID1, false, CreateFactory, nullptr },
michael@0 233 { &kFactoryCID2, false, CreateFactory, nullptr },
michael@0 234 { nullptr }
michael@0 235 };
michael@0 236
michael@0 237 static const mozilla::Module::ContractIDEntry kLocalContracts[] = {
michael@0 238 { FACTORY_CONTRACTID, &kFactoryCID2 },
michael@0 239 { nullptr }
michael@0 240 };
michael@0 241
michael@0 242 static const mozilla::Module kLocalModule = {
michael@0 243 mozilla::Module::kVersion,
michael@0 244 kLocalCIDs,
michael@0 245 kLocalContracts
michael@0 246 };
michael@0 247
michael@0 248 int main(int argc, char** argv)
michael@0 249 {
michael@0 250 nsresult rv;
michael@0 251 XRE_AddStaticComponent(&kLocalModule);
michael@0 252
michael@0 253 ScopedXPCOM xpcom("RacingServiceManager");
michael@0 254 NS_ENSURE_FALSE(xpcom.failed(), 1);
michael@0 255
michael@0 256 AutoCreateAndDestroyReentrantMonitor mon(&gReentrantMonitor);
michael@0 257
michael@0 258 nsRefPtr<Runnable> runnable = new Runnable();
michael@0 259 NS_ENSURE_TRUE(runnable, 1);
michael@0 260
michael@0 261 // Run the classID test
michael@0 262 nsCOMPtr<nsIThread> newThread;
michael@0 263 rv = NS_NewThread(getter_AddRefs(newThread), runnable);
michael@0 264 NS_ENSURE_SUCCESS(rv, 1);
michael@0 265
michael@0 266 {
michael@0 267 ReentrantMonitorAutoEnter mon(*gReentrantMonitor);
michael@0 268
michael@0 269 gMainThreadWaiting = true;
michael@0 270 mon.Notify();
michael@0 271
michael@0 272 while (!gCreateInstanceCalled) {
michael@0 273 mon.Wait();
michael@0 274 }
michael@0 275 }
michael@0 276
michael@0 277 nsCOMPtr<nsISupports> component(do_GetService(kFactoryCID1, &rv));
michael@0 278 NS_ENSURE_SUCCESS(rv, 1);
michael@0 279
michael@0 280 // Reset for the contractID test
michael@0 281 gMainThreadWaiting = gCreateInstanceCalled = false;
michael@0 282 gFactory->mFirstComponentCreated = runnable->mFirstRunnableDone = true;
michael@0 283 component = nullptr;
michael@0 284
michael@0 285 rv = newThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
michael@0 286 NS_ENSURE_SUCCESS(rv, 1);
michael@0 287
michael@0 288 {
michael@0 289 ReentrantMonitorAutoEnter mon(*gReentrantMonitor);
michael@0 290
michael@0 291 gMainThreadWaiting = true;
michael@0 292 mon.Notify();
michael@0 293
michael@0 294 while (!gCreateInstanceCalled) {
michael@0 295 mon.Wait();
michael@0 296 }
michael@0 297 }
michael@0 298
michael@0 299 component = do_GetService(FACTORY_CONTRACTID, &rv);
michael@0 300 NS_ENSURE_SUCCESS(rv, 1);
michael@0 301
michael@0 302 NS_RELEASE(gFactory);
michael@0 303
michael@0 304 return 0;
michael@0 305 }

mercurial