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

Unified Diff: cc/test/ordered_simple_task_runner.cc

Issue 387493002: Fixing and enhancing OrderedSimpleTaskRunner to allow 100% deterministic tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing the gn build. Created 6 years, 4 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: cc/test/ordered_simple_task_runner.cc
diff --git a/cc/test/ordered_simple_task_runner.cc b/cc/test/ordered_simple_task_runner.cc
index 188ffe72b5f8adea6208635d68263b3139811000..de7223efb9e61d6afb220ab15d6f2d9cd4208db5 100644
--- a/cc/test/ordered_simple_task_runner.cc
+++ b/cc/test/ordered_simple_task_runner.cc
@@ -6,8 +6,18 @@
#include <algorithm>
#include <deque>
+#include <sstream>
+#include <string>
-#include "base/logging.h"
+#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
+#include "base/strings/string_number_conversions.h"
+
+#define TRACE_TASK(function, task) \
+ TRACE_EVENT_INSTANT1( \
+ "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", TaskAsValue(task));
+
+#define TRACE_TASK_RUN(function, tag, task)
namespace {
@@ -16,26 +26,166 @@ bool TestPendingTaskComparator(const base::TestPendingTask& lhs,
return lhs.ShouldRunBefore(rhs);
}
+void TaskAsValueInto(const base::TestPendingTask& task,
+ base::debug::TracedValue* state) {
+ state->SetInteger("run_at", task.GetTimeToRun().ToInternalValue());
+ state->SetString("posted_from", task.location.ToString());
}
+scoped_refptr<base::debug::ConvertableToTraceFormat> TaskAsValue(
+ const base::TestPendingTask& task) {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
+ TaskAsValueInto(task, state);
+ return state;
+}
+
+} // namespace
+
namespace cc {
-OrderedSimpleTaskRunner::OrderedSimpleTaskRunner() {}
+void OrderedSimpleTaskRunner::SortTasks(
+ std::deque<base::TestPendingTask>* tasks) {
+ std::stable_sort(tasks->begin(), tasks->end(), TestPendingTaskComparator);
+}
+
+OrderedSimpleTaskRunner::OrderedSimpleTaskRunner()
+ : advance_now_(true),
+ now_src_(TestNowSource::Create()),
+ inside_run_pending_tasks_(false) {
+}
+
+OrderedSimpleTaskRunner::OrderedSimpleTaskRunner(
+ scoped_refptr<TestNowSource> now_src,
+ bool advance_now)
+ : advance_now_(advance_now),
+ now_src_(now_src),
+ inside_run_pending_tasks_(false) {
+}
OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
+// base::TestSimpleTaskRunner implementation
+bool OrderedSimpleTaskRunner::PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ base::TestPendingTask pt(
+ from_here, task, now_src_->Now(), delay, base::TestPendingTask::NESTABLE);
+
+ TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt);
+
+ pending_tasks_.push_back(pt);
+ SortTasks(&pending_tasks_);
+ return true;
+}
+
+bool OrderedSimpleTaskRunner::PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ base::TestPendingTask pt(from_here,
+ task,
+ now_src_->Now(),
+ delay,
+ base::TestPendingTask::NON_NESTABLE);
+
+ TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt);
+
+ pending_tasks_.push_back(pt);
+ SortTasks(&pending_tasks_);
+ return true;
+}
+
void OrderedSimpleTaskRunner::RunPendingTasks() {
+ TRACE_EVENT1(
+ "cc", "OrderedSimpleTaskRunner::RunPendingTasks", "this", AsValue());
DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (inside_run_pending_tasks_)
+ return;
+ inside_run_pending_tasks_ = true;
+
// Swap with a local variable to avoid re-entrancy problems.
std::deque<base::TestPendingTask> tasks_to_run;
tasks_to_run.swap(pending_tasks_);
- std::stable_sort(tasks_to_run.begin(),
- tasks_to_run.end(),
- TestPendingTaskComparator);
- for (std::deque<base::TestPendingTask>::iterator it = tasks_to_run.begin();
- it != tasks_to_run.end(); ++it) {
- it->task.Run();
+
+ std::deque<base::TestPendingTask>::iterator it = tasks_to_run.begin();
+ for (; it != tasks_to_run.end(); ++it) {
+ base::TimeTicks task_time = it->GetTimeToRun();
+
+ // Have new items been added to pending_tasks which need to run before this
+ // task?
+ if (pending_tasks_.size() > 0 &&
+ task_time > pending_tasks_.begin()->GetTimeToRun()) {
+ break;
+ }
+
+ // Is the task in the future?
+ if (task_time > now_src_->Now()) {
+ if (!advance_now_)
+ break;
+ else
+ now_src_->SetNow(task_time);
+ }
+
+ {
+ TRACE_EVENT1("cc",
+ "OrderedSimpleTaskRunner::RunPendingTasks running",
+ "task",
+ TaskAsValue(*it));
+ it->task.Run();
+ }
+ }
+
+ // Push any remaining tasks back into the pending queue
+ for (; it != tasks_to_run.end(); ++it) {
+ pending_tasks_.push_front(*it);
+ }
+ SortTasks(&pending_tasks_);
+
+ inside_run_pending_tasks_ = false;
+}
+
+base::TimeDelta OrderedSimpleTaskRunner::DelayToNextPendingTask() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ base::TimeDelta delay =
+ pending_tasks_.front().GetTimeToRun() - now_src_->Now();
+ if (delay > base::TimeDelta())
+ return delay;
+ return base::TimeDelta();
+}
+
+void OrderedSimpleTaskRunner::SetAutoAdvanceNowToPendingTasks(
+ bool advance_now) {
+ advance_now_ = advance_now;
+}
+
+// base::debug tracing functionality
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+OrderedSimpleTaskRunner::AsValue() const {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
+ AsValueInto(state);
+ return state;
+}
+
+void OrderedSimpleTaskRunner::AsValueInto(
+ base::debug::TracedValue* state) const {
+ state->SetInteger("pending_tasks", pending_tasks_.size());
+ for (std::deque<base::TestPendingTask>::const_iterator it =
+ pending_tasks_.begin();
+ it != pending_tasks_.end();
+ ++it) {
+ state->BeginDictionary(
+ base::SizeTToString(std::distance(pending_tasks_.begin(), it)).c_str());
+ TaskAsValueInto(*it, state);
+ state->EndDictionary();
}
+ now_src_->AsValueInto(state);
}
} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698