C++程序  |  155行  |  5.62 KB

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
#define CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_

#include <limits>
#include <set>
#include <vector>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/test/test_simple_task_runner.h"
#include "cc/test/test_now_source.h"

namespace cc {

// Subclass of TestPendingTask which has a unique ID for every task, supports
// being used inside a std::set and has debug tracing support.
class TestOrderablePendingTask : public base::TestPendingTask {
 public:
  TestOrderablePendingTask();
  TestOrderablePendingTask(const tracked_objects::Location& location,
                           const base::Closure& task,
                           base::TimeTicks post_time,
                           base::TimeDelta delay,
                           TestNestability nestability);
  ~TestOrderablePendingTask();

  // operators needed by std::set and comparison
  bool operator==(const TestOrderablePendingTask& other) const;
  bool operator<(const TestOrderablePendingTask& other) const;

  // debug tracing functions
  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
  void AsValueInto(base::debug::TracedValue* state) const;

 private:
  static size_t task_id_counter;
  const size_t task_id_;
};

// This runs pending tasks based on task's post_time + delay.
// We should not execute a delayed task sooner than some of the queued tasks
// which don't have a delay even though it is queued early.
class OrderedSimpleTaskRunner : public base::SingleThreadTaskRunner {
 public:
  OrderedSimpleTaskRunner();
  OrderedSimpleTaskRunner(scoped_refptr<TestNowSource> now_src,
                          bool advance_now);

  // base::TestSimpleTaskRunner implementation:
  virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
                               const base::Closure& task,
                               base::TimeDelta delay) OVERRIDE;
  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      base::TimeDelta delay) OVERRIDE;

  virtual bool RunsTasksOnCurrentThread() const OVERRIDE;

  // Set a maximum number of tasks to run at once. Useful as a timeout to
  // prevent infinite task loops.
  static const size_t kAbsoluteMaxTasks;
  void SetRunTaskLimit(size_t max_tasks) { max_tasks_ = max_tasks; }
  void ClearRunTaskLimit() { max_tasks_ = kAbsoluteMaxTasks; }

  // Allow task runner to advance now when running tasks.
  void SetAutoAdvanceNowToPendingTasks(bool advance_now) {
    advance_now_ = advance_now;
  }

  base::TimeTicks NextTaskTime();
  base::TimeDelta DelayToNextTaskTime();

  // Run tasks while the callback returns true or too many tasks have been run.
  // Returns true if there are still pending tasks left.
  bool RunTasksWhile(base::Callback<bool(void)> condition);

  // Run tasks while *all* of the callbacks return true or too many tasks have
  // been run. Exits on the *first* condition which returns false, skipping
  // calling all remaining conditions. Conditions can have side effects,
  // including modifying the task queue.
  // Returns true if there are still pending tasks left.
  bool RunTasksWhile(
      const std::vector<base::Callback<bool(void)> >& conditions);

  // Convenience functions to run tasks with common conditions.

  // Run tasks which existed at the start of this call.
  // Return code indicates tasks still exist to run.
  bool RunPendingTasks();
  // Keep running tasks until no tasks are left.
  // Return code indicates tasks still exist to run which also indicates if
  // runner reached idle.
  bool RunUntilIdle();
  // Keep running tasks until given time period.
  // Return code indicates tasks still exist to run.
  bool RunUntilTime(base::TimeTicks time);
  bool RunForPeriod(base::TimeDelta period);

  // base::debug tracing functionality
  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
  virtual void AsValueInto(base::debug::TracedValue* state) const;

  // Common conditions to run for, exposed publicly to allow external users to
  // use their own combinations.
  // -------------------------------------------------------------------------

  // Keep running until the given number of tasks have run.
  // You generally shouldn't use this check as it will cause your tests to fail
  // when code is changed adding a new task. It is useful as a "timeout" type
  // solution.
  base::Callback<bool(void)> TaskRunCountBelow(size_t max_tasks);

  // Keep running until a task which didn't exist initially would run.
  base::Callback<bool(void)> TaskExistedInitially();

  // Stop running tasks when NextTaskTime() >= stop_at
  base::Callback<bool(void)> NowBefore(base::TimeTicks stop_at);

  // Advance Now() to the next task to run.
  base::Callback<bool(void)> AdvanceNow();

 protected:
  static bool TaskRunCountBelowCallback(size_t max_tasks, size_t* task_run);
  bool TaskExistedInitiallyCallback(
      const std::set<TestOrderablePendingTask>& existing_tasks);
  bool NowBeforeCallback(base::TimeTicks stop_at);
  bool AdvanceNowCallback();

  virtual ~OrderedSimpleTaskRunner();

  base::ThreadChecker thread_checker_;

  bool advance_now_;
  scoped_refptr<TestNowSource> now_src_;

  size_t max_tasks_;

  bool inside_run_tasks_until_;
  std::set<TestOrderablePendingTask> pending_tasks_;

 private:
  DISALLOW_COPY_AND_ASSIGN(OrderedSimpleTaskRunner);
};

}  // namespace cc

#endif  // CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_