Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2873)

Unified Diff: components/timers/alarm_timer_unittest.cc

Issue 2398753003: Use FileDescriptorWatcher in AlarmTimer. (Closed)
Patch Set: fix build error Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/timers/alarm_timer_unittest.cc
diff --git a/components/timers/alarm_timer_unittest.cc b/components/timers/alarm_timer_unittest.cc
index 2b9663dc65ad37612296cb0d7b6fc8b4244cd8c9..2dbd51bfd81cc1700822e03d5f9d8d9fd4fc6885 100644
--- a/components/timers/alarm_timer_unittest.cc
+++ b/components/timers/alarm_timer_unittest.cc
@@ -8,8 +8,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/files/file_descriptor_watcher_posix.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -23,22 +25,8 @@
// cosmetic changes (like replacing calls to MessageLoop::current()->Run() with
// a RunLoop). We want the AlarmTimer to be a drop-in replacement for the
// regular Timer so it should pass the same tests as the Timer class.
-//
-// The only new tests are the .*ConcurrentResetAndTimerFired tests, which test
-// that race conditions that can come up in the AlarmTimer::Delegate are
-// properly handled.
namespace timers {
namespace {
-// The message loops on which each timer should be tested.
-const base::MessageLoop::Type testing_message_loops[] = {
- base::MessageLoop::TYPE_DEFAULT,
- base::MessageLoop::TYPE_IO,
-#if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
- base::MessageLoop::TYPE_UI,
-#endif
-};
-
-const int kNumTestingMessageLoops = arraysize(testing_message_loops);
const base::TimeDelta kTenMilliseconds = base::TimeDelta::FromMilliseconds(10);
class OneShotAlarmTimerTester {
@@ -133,136 +121,129 @@ class RepeatingAlarmTimerTester {
// that timers work properly in all configurations.
TEST(AlarmTimerTest, OneShotAlarmTimer) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run = false;
- OneShotAlarmTimerTester f(&did_run, kTenMilliseconds);
- f.Start();
+ bool did_run = false;
+ OneShotAlarmTimerTester f(&did_run, kTenMilliseconds);
+ f.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_TRUE(did_run);
- }
+ EXPECT_TRUE(did_run);
}
TEST(AlarmTimerTest, OneShotAlarmTimer_Cancel) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run_a = false;
- OneShotAlarmTimerTester* a =
- new OneShotAlarmTimerTester(&did_run_a, kTenMilliseconds);
+ bool did_run_a = false;
+ OneShotAlarmTimerTester* a =
+ new OneShotAlarmTimerTester(&did_run_a, kTenMilliseconds);
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
+ // This should run before the timer expires.
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
- // Now start the timer.
- a->Start();
+ // Now start the timer.
+ a->Start();
- bool did_run_b = false;
- OneShotAlarmTimerTester b(&did_run_b, kTenMilliseconds);
- b.Start();
+ bool did_run_b = false;
+ OneShotAlarmTimerTester b(&did_run_b, kTenMilliseconds);
+ b.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
- }
+ EXPECT_FALSE(did_run_a);
+ EXPECT_TRUE(did_run_b);
}
// If underlying timer does not handle this properly, we will crash or fail
// in full page heap environment.
TEST(AlarmTimerTest, OneShotSelfDeletingAlarmTimer) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run = false;
- OneShotSelfDeletingAlarmTimerTester f(&did_run, kTenMilliseconds);
- f.Start();
+ bool did_run = false;
+ OneShotSelfDeletingAlarmTimerTester f(&did_run, kTenMilliseconds);
+ f.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_TRUE(did_run);
- }
+ EXPECT_TRUE(did_run);
}
TEST(AlarmTimerTest, RepeatingAlarmTimer) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run = false;
- RepeatingAlarmTimerTester f(&did_run, kTenMilliseconds);
- f.Start();
+ bool did_run = false;
+ RepeatingAlarmTimerTester f(&did_run, kTenMilliseconds);
+ f.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_TRUE(did_run);
- }
+ EXPECT_TRUE(did_run);
}
TEST(AlarmTimerTest, RepeatingAlarmTimer_Cancel) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run_a = false;
- RepeatingAlarmTimerTester* a =
- new RepeatingAlarmTimerTester(&did_run_a, kTenMilliseconds);
+ bool did_run_a = false;
+ RepeatingAlarmTimerTester* a =
+ new RepeatingAlarmTimerTester(&did_run_a, kTenMilliseconds);
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
+ // This should run before the timer expires.
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
- // Now start the timer.
- a->Start();
+ // Now start the timer.
+ a->Start();
- bool did_run_b = false;
- RepeatingAlarmTimerTester b(&did_run_b, kTenMilliseconds);
- b.Start();
+ bool did_run_b = false;
+ RepeatingAlarmTimerTester b(&did_run_b, kTenMilliseconds);
+ b.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
- }
+ EXPECT_FALSE(did_run_a);
+ EXPECT_TRUE(did_run_b);
}
TEST(AlarmTimerTest, RepeatingAlarmTimerZeroDelay) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run = false;
- RepeatingAlarmTimerTester f(&did_run, base::TimeDelta());
- f.Start();
+ bool did_run = false;
+ RepeatingAlarmTimerTester f(&did_run, base::TimeDelta());
+ f.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_TRUE(did_run);
- }
+ EXPECT_TRUE(did_run);
}
TEST(AlarmTimerTest, RepeatingAlarmTimerZeroDelay_Cancel) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- bool did_run_a = false;
- RepeatingAlarmTimerTester* a =
- new RepeatingAlarmTimerTester(&did_run_a, base::TimeDelta());
+ bool did_run_a = false;
+ RepeatingAlarmTimerTester* a =
+ new RepeatingAlarmTimerTester(&did_run_a, base::TimeDelta());
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
+ // This should run before the timer expires.
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
- // Now start the timer.
- a->Start();
+ // Now start the timer.
+ a->Start();
- bool did_run_b = false;
- RepeatingAlarmTimerTester b(&did_run_b, base::TimeDelta());
- b.Start();
+ bool did_run_b = false;
+ RepeatingAlarmTimerTester b(&did_run_b, base::TimeDelta());
+ b.Start();
- base::RunLoop().Run();
+ base::RunLoop().Run();
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
- }
+ EXPECT_FALSE(did_run_a);
+ EXPECT_TRUE(did_run_b);
}
TEST(AlarmTimerTest, MessageLoopShutdown) {
@@ -272,23 +253,29 @@ TEST(AlarmTimerTest, MessageLoopShutdown) {
// if debug heap checking is enabled.
bool did_run = false;
{
+ auto loop = base::MakeUnique<base::MessageLoopForIO>();
+ auto file_descriptor_watcher =
+ base::MakeUnique<base::FileDescriptorWatcher>(loop.get());
OneShotAlarmTimerTester a(&did_run, kTenMilliseconds);
OneShotAlarmTimerTester b(&did_run, kTenMilliseconds);
OneShotAlarmTimerTester c(&did_run, kTenMilliseconds);
OneShotAlarmTimerTester d(&did_run, kTenMilliseconds);
- {
- base::MessageLoop loop;
- a.Start();
- b.Start();
- } // MessageLoop destructs by falling out of scope.
- } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
+
+ a.Start();
+ b.Start();
+
+ // MessageLoop and FileDescriptorWatcher destruct.
+ file_descriptor_watcher.reset();
+ loop.reset();
+ } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
EXPECT_FALSE(did_run);
}
TEST(AlarmTimerTest, NonRepeatIsRunning) {
{
- base::MessageLoop loop;
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
timers::OneShotAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
@@ -300,8 +287,9 @@ TEST(AlarmTimerTest, NonRepeatIsRunning) {
}
{
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
timers::SimpleAlarmTimer timer;
- base::MessageLoop loop;
EXPECT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
base::Bind(&base::DoNothing));
@@ -314,24 +302,14 @@ TEST(AlarmTimerTest, NonRepeatIsRunning) {
}
}
-TEST(AlarmTimerTest, NonRepeatMessageLoopDeath) {
- timers::OneShotAlarmTimer timer;
- {
- base::MessageLoop loop;
- EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
- EXPECT_TRUE(timer.IsRunning());
- }
- EXPECT_FALSE(timer.IsRunning());
- EXPECT_TRUE(timer.user_task().is_null());
-}
-
TEST(AlarmTimerTest, RetainRepeatIsRunning) {
- base::MessageLoop loop;
- timers::RepeatingAlarmTimer timer(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
+ timers::RepeatingAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
+ timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
+ base::Bind(&base::DoNothing));
+ EXPECT_TRUE(timer.IsRunning());
timer.Reset();
EXPECT_TRUE(timer.IsRunning());
timer.Stop();
@@ -341,10 +319,13 @@ TEST(AlarmTimerTest, RetainRepeatIsRunning) {
}
TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
- base::MessageLoop loop;
- timers::SimpleAlarmTimer timer(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
+ timers::SimpleAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
+ timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
+ base::Bind(&base::DoNothing));
+ EXPECT_TRUE(timer.IsRunning());
timer.Reset();
EXPECT_TRUE(timer.IsRunning());
timer.Stop();
@@ -376,142 +357,75 @@ void SetCallbackHappened2() {
}
TEST(AlarmTimerTest, ContinuationStopStart) {
- {
- ClearAllCallbackHappened();
- base::MessageLoop loop;
- timers::OneShotAlarmTimer timer;
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::Bind(&SetCallbackHappened1));
- timer.Stop();
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
- base::Bind(&SetCallbackHappened2));
- base::RunLoop().Run();
- EXPECT_FALSE(g_callback_happened1);
- EXPECT_TRUE(g_callback_happened2);
- }
+ ClearAllCallbackHappened();
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
+ timers::OneShotAlarmTimer timer;
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
+ base::Bind(&SetCallbackHappened1));
+ timer.Stop();
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
+ base::Bind(&SetCallbackHappened2));
+ base::RunLoop().Run();
+ EXPECT_FALSE(g_callback_happened1);
+ EXPECT_TRUE(g_callback_happened2);
}
TEST(AlarmTimerTest, ContinuationReset) {
- {
- ClearAllCallbackHappened();
- base::MessageLoop loop;
- timers::OneShotAlarmTimer timer;
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::Bind(&SetCallbackHappened1));
- timer.Reset();
- // Since Reset happened before task ran, the user_task must not be cleared:
- ASSERT_FALSE(timer.user_task().is_null());
- base::RunLoop().Run();
- EXPECT_TRUE(g_callback_happened1);
- }
-}
-
-} // namespace
-
-namespace {
-void TimerRanCallback(bool* did_run) {
- *did_run = true;
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
-}
-
-bool IsAlarmTimerSupported() {
- int fd = timerfd_create(CLOCK_REALTIME_ALARM, 0);
-
- if (fd == -1) {
- LOG(WARNING) << "CLOCK_REALTIME_ALARM is not supported on this system. "
- << "Skipping test. Upgrade to at least linux version 3.11 to "
- << "support this timer.";
- return false;
- }
-
- close(fd);
- return true;
+ ClearAllCallbackHappened();
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
+ timers::OneShotAlarmTimer timer;
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
+ base::Bind(&SetCallbackHappened1));
+ timer.Reset();
+ // Since Reset happened before task ran, the user_task must not be cleared:
+ ASSERT_FALSE(timer.user_task().is_null());
+ base::RunLoop().Run();
+ EXPECT_TRUE(g_callback_happened1);
}
-TEST(AlarmTimerTest, OneShotTimerConcurrentResetAndTimerFired) {
- // The "Linux ChromiumOS .*" bots are still running Ubuntu 12.04, which
- // doesn't have a linux version high enough to support the AlarmTimer. Since
- // this test depends on SetTimerFiredCallbackForTest(), which is specific to
- // the AlarmTimer, we have to just skip the test to stop it from failing.
- if (!IsAlarmTimerSupported())
- return;
-
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
-
- timers::OneShotAlarmTimer timer;
- bool did_run = false;
-
- base::RunLoop run_loop;
-
- timer.SetTimerFiredCallbackForTest(run_loop.QuitClosure());
- timer.Start(FROM_HERE, kTenMilliseconds,
- base::Bind(&TimerRanCallback, &did_run));
-
- // Wait until the timer has fired and a task has been queue in the
- // MessageLoop.
- run_loop.Run();
-
- // Now reset the timer. This is attempting to simulate the timer firing and
- // being reset at the same time. The previously queued task should be
- // removed.
- timer.Reset();
-
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(did_run);
-
- // If the previous check failed, running the message loop again will hang
- // the test so we only do it if the callback has not run yet.
- if (!did_run) {
- base::RunLoop().Run();
- EXPECT_TRUE(did_run);
- }
- }
+// Verify that no crash occurs if a timer is deleted while its callback is
+// running.
+TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunning) {
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
+ base::RunLoop run_loop;
+
+ // Will be deleted by the callback.
+ timers::OneShotAlarmTimer* timer = new timers::OneShotAlarmTimer;
+
+ timer->Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(10),
+ base::Bind(
+ [](timers::OneShotAlarmTimer* timer, base::RunLoop* run_loop) {
+ delete timer;
+ run_loop->Quit();
+ },
+ timer, &run_loop));
+ run_loop.Run();
}
-TEST(AlarmTimerTest, RepeatingTimerConcurrentResetAndTimerFired) {
- // The "Linux ChromiumOS .*" bots are still running Ubuntu 12.04, which
- // doesn't have a linux version high enough to support the AlarmTimer. Since
- // this test depends on SetTimerFiredCallbackForTest(), which is specific to
- // the AlarmTimer, we have to just skip the test to stop it from failing.
- if (!IsAlarmTimerSupported())
- return;
-
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- base::MessageLoop loop(testing_message_loops[i]);
-
- timers::RepeatingAlarmTimer timer;
- bool did_run = false;
-
- base::RunLoop run_loop;
-
- timer.SetTimerFiredCallbackForTest(run_loop.QuitClosure());
- timer.Start(FROM_HERE, kTenMilliseconds,
- base::Bind(&TimerRanCallback, &did_run));
-
- // Wait until the timer has fired and a task has been queue in the
- // MessageLoop.
- run_loop.Run();
-
- // Now reset the timer. This is attempting to simulate the timer firing and
- // being reset at the same time. The previously queued task should be
- // removed.
- timer.Reset();
-
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(did_run);
-
- // If the previous check failed, running the message loop again will hang
- // the test so we only do it if the callback has not run yet.
- if (!did_run) {
- base::RunLoop().Run();
- EXPECT_TRUE(did_run);
- }
- }
+// Verify that no crash occurs if a zero-delay timer is deleted while its
+// callback is running.
+TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunningZeroDelay) {
+ base::MessageLoopForIO loop;
+ base::FileDescriptorWatcher file_descriptor_watcher(&loop);
+ base::RunLoop run_loop;
+
+ // Will be deleted by the callback.
+ timers::OneShotAlarmTimer* timer = new timers::OneShotAlarmTimer;
+
+ timer->Start(
+ FROM_HERE, base::TimeDelta(),
+ base::Bind(
+ [](timers::OneShotAlarmTimer* timer, base::RunLoop* run_loop) {
+ delete timer;
+ run_loop->Quit();
+ },
+ timer, &run_loop));
+ run_loop.Run();
}
} // namespace
-
} // namespace timers
« components/timers/alarm_timer_chromeos.cc ('K') | « components/timers/alarm_timer_chromeos.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698