test_task_runner: Implement AdvanceTimeAndRunUntilIdle() This is useful to fake time in tests, to quickly simulate long timeouts. It requires touching the UnixTaskRunner implementation. Change-Id: I53eb71a90194abecc7008342601711124b8889cb
diff --git a/include/perfetto/ext/base/unix_task_runner.h b/include/perfetto/ext/base/unix_task_runner.h index ecde733..9ca6638 100644 --- a/include/perfetto/ext/base/unix_task_runner.h +++ b/include/perfetto/ext/base/unix_task_runner.h
@@ -69,6 +69,10 @@ // delayed tasks don't count even if they are due to run. bool IsIdleForTesting(); + // Pretends (for the purposes of running delayed tasks) that time advanced by + // `ms`. + void AdvanceTimeForTesting(uint32_t ms); + // TaskRunner implementation: void PostTask(std::function<void()>) override; void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override; @@ -108,6 +112,7 @@ std::deque<std::function<void()>> immediate_tasks_; std::multimap<TimeMillis, std::function<void()>> delayed_tasks_; bool quit_ = false; + TimeMillis advanced_time_for_testing_ = TimeMillis(0); struct WatchTask { std::function<void()> callback;
diff --git a/src/base/test/test_task_runner.cc b/src/base/test/test_task_runner.cc index 3576996..51d6d52 100644 --- a/src/base/test/test_task_runner.cc +++ b/src/base/test/test_task_runner.cc
@@ -88,6 +88,14 @@ }; } +void TestTaskRunner::AdvanceTimeAndRunUntilIdle(uint32_t ms) { + PERFETTO_DCHECK_THREAD(thread_checker_); + task_runner_.PostDelayedTask(std::bind(&TestTaskRunner::QuitIfIdle, this), + ms); + task_runner_.AdvanceTimeForTesting(ms); + task_runner_.Run(); +} + // TaskRunner implementation. void TestTaskRunner::PostTask(std::function<void()> closure) { task_runner_.PostTask(std::move(closure));
diff --git a/src/base/test/test_task_runner.h b/src/base/test/test_task_runner.h index a7c5784..142970d 100644 --- a/src/base/test/test_task_runner.h +++ b/src/base/test/test_task_runner.h
@@ -42,6 +42,10 @@ void RunUntilCheckpoint(const std::string& checkpoint, uint32_t timeout_ms = 5000); + // Pretends (for the purposes of running delayed tasks) that time advanced by + // `ms`. Run until then. + void AdvanceTimeAndRunUntilIdle(uint32_t ms); + // TaskRunner implementation. void PostTask(std::function<void()> closure) override; void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc index ba2828f..4288f20 100644 --- a/src/base/unix_task_runner.cc +++ b/src/base/unix_task_runner.cc
@@ -108,6 +108,11 @@ return immediate_tasks_.empty(); } +void UnixTaskRunner::AdvanceTimeForTesting(uint32_t ms) { + std::lock_guard<std::mutex> lock(lock_); + advanced_time_for_testing_ += TimeMillis(ms); +} + void UnixTaskRunner::UpdateWatchTasksLocked() { PERFETTO_DCHECK_THREAD(thread_checker_); #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) @@ -142,7 +147,7 @@ } if (!delayed_tasks_.empty()) { auto it = delayed_tasks_.begin(); - if (now >= it->first) { + if (now + advanced_time_for_testing_ >= it->first) { delayed_task = std::move(it->second); delayed_tasks_.erase(it); } @@ -242,7 +247,8 @@ if (!immediate_tasks_.empty()) return 0; if (!delayed_tasks_.empty()) { - TimeMillis diff = delayed_tasks_.begin()->first - GetWallTimeMs(); + TimeMillis diff = delayed_tasks_.begin()->first - GetWallTimeMs() - + advanced_time_for_testing_; return std::max(0, static_cast<int>(diff.count())); } return -1; @@ -264,7 +270,8 @@ TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms); { std::lock_guard<std::mutex> lock(lock_); - delayed_tasks_.insert(std::make_pair(runtime, std::move(task))); + delayed_tasks_.insert( + std::make_pair(runtime + advanced_time_for_testing_, std::move(task))); } WakeUp(); }