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"
12 #include "nsComponentManagerUtils.h"
13 #include "nsServiceManagerUtils.h"
14 #include "nsThreadUtils.h"
18 #include "mozilla/Attributes.h"
20 #include "mozilla/ReentrantMonitor.h"
21 using namespace mozilla
;
23 typedef nsresult(*TestFuncPtr
)();
29 nsCOMPtr
<nsIThread
> newThread
;
30 nsresult rv
= NS_NewThread(getter_AddRefs(newThread
));
34 newThread
.swap(mThread
);
41 operator nsIThread
*() const {
45 nsIThread
* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
{
50 nsCOMPtr
<nsIThread
> mThread
;
53 class AutoCreateAndDestroyReentrantMonitor
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
;
70 ReentrantMonitor
* mReentrantMonitor
;
73 class TimerCallback MOZ_FINAL
: public nsITimerCallback
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
;
97 nsIThread
** mThreadPtr
;
98 ReentrantMonitor
* mReentrantMonitor
;
101 NS_IMPL_ISUPPORTS(TimerCallback
, nsITimerCallback
)
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
);
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(¬ifiedThread
, 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
) {
135 NS_ENSURE_TRUE(notifiedThread
== testThread
, NS_ERROR_FAILURE
);
141 TestTimerWithStoppedTarget()
143 AutoTestThread testThread
;
144 NS_ENSURE_TRUE(testThread
, NS_ERROR_OUT_OF_MEMORY
);
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();
171 int main(int argc
, char** argv
)
173 ScopedXPCOM
xpcom("TestTimers");
174 NS_ENSURE_FALSE(xpcom
.failed(), 1);
176 static TestFuncPtr testsToRun
[] = {
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);