Bumping gaia.json for 8 gaia revision(s) a=gaia-bump
[gecko.git] / xpcom / tests / TestTimers.cpp
blobe2c33e55d7dafc7a9ddedd7fb0c4ed2a00bcd956
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "TestHarness.h"
8 #include "nsIThread.h"
9 #include "nsITimer.h"
11 #include "nsCOMPtr.h"
12 #include "nsComponentManagerUtils.h"
13 #include "nsServiceManagerUtils.h"
14 #include "nsThreadUtils.h"
15 #include "prinrval.h"
16 #include "prmon.h"
17 #include "prthread.h"
18 #include "mozilla/Attributes.h"
20 #include "mozilla/ReentrantMonitor.h"
21 using namespace mozilla;
23 typedef nsresult(*TestFuncPtr)();
25 class AutoTestThread
27 public:
28 AutoTestThread() {
29 nsCOMPtr<nsIThread> newThread;
30 nsresult rv = NS_NewThread(getter_AddRefs(newThread));
31 if (NS_FAILED(rv))
32 return;
34 newThread.swap(mThread);
37 ~AutoTestThread() {
38 mThread->Shutdown();
41 operator nsIThread*() const {
42 return mThread;
45 nsIThread* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
46 return mThread;
49 private:
50 nsCOMPtr<nsIThread> mThread;
53 class AutoCreateAndDestroyReentrantMonitor
55 public:
56 AutoCreateAndDestroyReentrantMonitor() {
57 mReentrantMonitor = new ReentrantMonitor("TestTimers::AutoMon");
58 NS_ASSERTION(mReentrantMonitor, "Out of memory!");
61 ~AutoCreateAndDestroyReentrantMonitor() {
62 delete mReentrantMonitor;
65 operator ReentrantMonitor* () {
66 return mReentrantMonitor;
69 private:
70 ReentrantMonitor* mReentrantMonitor;
73 class TimerCallback MOZ_FINAL : public nsITimerCallback
75 public:
76 NS_DECL_THREADSAFE_ISUPPORTS
78 TimerCallback(nsIThread** aThreadPtr, ReentrantMonitor* aReentrantMonitor)
79 : mThreadPtr(aThreadPtr), mReentrantMonitor(aReentrantMonitor) { }
81 NS_IMETHOD Notify(nsITimer* aTimer) MOZ_OVERRIDE {
82 NS_ASSERTION(mThreadPtr, "Callback was not supposed to be called!");
83 nsCOMPtr<nsIThread> current(do_GetCurrentThread());
85 ReentrantMonitorAutoEnter mon(*mReentrantMonitor);
87 NS_ASSERTION(!*mThreadPtr, "Timer called back more than once!");
88 *mThreadPtr = current;
90 mon.Notify();
92 return NS_OK;
94 private:
95 ~TimerCallback() {}
97 nsIThread** mThreadPtr;
98 ReentrantMonitor* mReentrantMonitor;
101 NS_IMPL_ISUPPORTS(TimerCallback, nsITimerCallback)
103 nsresult
104 TestTargetedTimers()
106 AutoCreateAndDestroyReentrantMonitor newMon;
107 NS_ENSURE_TRUE(newMon, NS_ERROR_OUT_OF_MEMORY);
109 AutoTestThread testThread;
110 NS_ENSURE_TRUE(testThread, NS_ERROR_OUT_OF_MEMORY);
112 nsresult rv;
113 nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
114 NS_ENSURE_SUCCESS(rv, rv);
116 nsIEventTarget* target = static_cast<nsIEventTarget*>(testThread);
118 rv = timer->SetTarget(target);
119 NS_ENSURE_SUCCESS(rv, rv);
121 nsIThread* notifiedThread = nullptr;
123 nsCOMPtr<nsITimerCallback> callback =
124 new TimerCallback(&notifiedThread, newMon);
125 NS_ENSURE_TRUE(callback, NS_ERROR_OUT_OF_MEMORY);
127 rv = timer->InitWithCallback(callback, PR_MillisecondsToInterval(2000),
128 nsITimer::TYPE_ONE_SHOT);
129 NS_ENSURE_SUCCESS(rv, rv);
131 ReentrantMonitorAutoEnter mon(*newMon);
132 while (!notifiedThread) {
133 mon.Wait();
135 NS_ENSURE_TRUE(notifiedThread == testThread, NS_ERROR_FAILURE);
137 return NS_OK;
140 nsresult
141 TestTimerWithStoppedTarget()
143 AutoTestThread testThread;
144 NS_ENSURE_TRUE(testThread, NS_ERROR_OUT_OF_MEMORY);
146 nsresult rv;
147 nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
148 NS_ENSURE_SUCCESS(rv, rv);
150 nsIEventTarget* target = static_cast<nsIEventTarget*>(testThread);
152 rv = timer->SetTarget(target);
153 NS_ENSURE_SUCCESS(rv, rv);
155 // If this is called, we'll assert
156 nsCOMPtr<nsITimerCallback> callback =
157 new TimerCallback(nullptr, nullptr);
158 NS_ENSURE_TRUE(callback, NS_ERROR_OUT_OF_MEMORY);
160 rv = timer->InitWithCallback(callback, PR_MillisecondsToInterval(100),
161 nsITimer::TYPE_ONE_SHOT);
162 NS_ENSURE_SUCCESS(rv, rv);
164 testThread->Shutdown();
166 PR_Sleep(400);
168 return NS_OK;
171 int main(int argc, char** argv)
173 ScopedXPCOM xpcom("TestTimers");
174 NS_ENSURE_FALSE(xpcom.failed(), 1);
176 static TestFuncPtr testsToRun[] = {
177 TestTargetedTimers,
178 TestTimerWithStoppedTarget
180 static uint32_t testCount = sizeof(testsToRun) / sizeof(testsToRun[0]);
182 for (uint32_t i = 0; i < testCount; i++) {
183 nsresult rv = testsToRun[i]();
184 NS_ENSURE_SUCCESS(rv, 1);
187 return 0;