// 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 COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
#define COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_

#include <stddef.h>

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

#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/trace_event/trace_event.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,
                           base::OnceClosure task,
                           base::TimeTicks post_time,
                           base::TimeDelta delay,
                           TestNestability nestability);
  TestOrderablePendingTask(TestOrderablePendingTask&&);
  ~TestOrderablePendingTask();

  TestOrderablePendingTask& operator=(TestOrderablePendingTask&&);

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

  // base::trace_event tracing functionality
  std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
  void AsValueInto(base::trace_event::TracedValue* state) const;

  size_t task_id() const { return task_id_; }

 private:
  static size_t task_id_counter;
  size_t task_id_;

  DISALLOW_COPY_AND_ASSIGN(TestOrderablePendingTask);
};

// 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(base::SimpleTestTickClock* now_src, bool advance_now);

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

  bool RunsTasksInCurrentSequence() 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;
  }

  size_t NumPendingTasks() const;
  bool HasPendingTasks() const;
  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::trace_event tracing functionality
  std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
  virtual void AsValueInto(base::trace_event::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();

  // Removes all tasks whose weak pointer has been revoked.
  void RemoveCancelledTasks();

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

  ~OrderedSimpleTaskRunner() override;

  base::ThreadChecker thread_checker_;

  bool advance_now_;
  // Not owned.
  base::SimpleTestTickClock* 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  // COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
