/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#if defined(WEBRTC_POSIX)
#include <sys/time.h>
#endif  // WEBRTC_POSIX

// TODO: Remove this once the cause of sporadic failures in these
// tests is tracked down.
#include <iostream>

#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h"
#endif  // WEBRTC_WIN

#include "webrtc/base/common.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/task.h"
#include "webrtc/base/taskrunner.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/test/testsupport/gtest_disable.h"

namespace rtc {

static int64_t GetCurrentTime() {
  return static_cast<int64_t>(Time()) * 10000;
}

// feel free to change these numbers.  Note that '0' won't work, though
#define STUCK_TASK_COUNT 5
#define HAPPY_TASK_COUNT 20

// this is a generic timeout task which, when it signals timeout, will
// include the unique ID of the task in the signal (we don't use this
// in production code because we haven't yet had occasion to generate
// an array of the same types of task)

class IdTimeoutTask : public Task, public sigslot::has_slots<> {
 public:
  explicit IdTimeoutTask(TaskParent *parent) : Task(parent) {
    SignalTimeout.connect(this, &IdTimeoutTask::OnLocalTimeout);
  }

  sigslot::signal1<const int> SignalTimeoutId;
  sigslot::signal1<const int> SignalDoneId;

  virtual int ProcessStart() {
    return STATE_RESPONSE;
  }

  void OnLocalTimeout() {
    SignalTimeoutId(unique_id());
  }

 protected:
  virtual void Stop() {
    SignalDoneId(unique_id());
    Task::Stop();
  }
};

class StuckTask : public IdTimeoutTask {
 public:
  explicit StuckTask(TaskParent *parent) : IdTimeoutTask(parent) {}
  virtual int ProcessStart() {
    return STATE_BLOCKED;
  }
};

class HappyTask : public IdTimeoutTask {
 public:
  explicit HappyTask(TaskParent *parent) : IdTimeoutTask(parent) {
    time_to_perform_ = rand() % (STUCK_TASK_COUNT / 2);
  }
  virtual int ProcessStart() {
    if (ElapsedTime() > (time_to_perform_ * 1000 * 10000))
      return STATE_RESPONSE;
    else
      return STATE_BLOCKED;
  }

 private:
  int time_to_perform_;
};

// simple implementation of a task runner which uses Windows'
// GetSystemTimeAsFileTime() to get the current clock ticks

class MyTaskRunner : public TaskRunner {
 public:
  virtual void WakeTasks() { RunTasks(); }
  virtual int64_t CurrentTime() { return GetCurrentTime(); }

  bool timeout_change() const {
    return timeout_change_;
  }

  void clear_timeout_change() {
    timeout_change_ = false;
  }
 protected:
  virtual void OnTimeoutChange() {
    timeout_change_ = true;
  }
  bool timeout_change_;
};

//
// this unit test is primarily concerned (for now) with the timeout
// functionality in tasks.  It works as follows:
//
//   * Create a bunch of tasks, some "stuck" (ie., guaranteed to timeout)
//     and some "happy" (will immediately finish).
//   * Set the timeout on the "stuck" tasks to some number of seconds between
//     1 and the number of stuck tasks
//   * Start all the stuck & happy tasks in random order
//   * Wait "number of stuck tasks" seconds and make sure everything timed out

class TaskTest : public sigslot::has_slots<> {
 public:
  TaskTest() {}

  // no need to delete any tasks; the task runner owns them
  ~TaskTest() {}

  void Start() {
    // create and configure tasks
    for (int i = 0; i < STUCK_TASK_COUNT; ++i) {
      stuck_[i].task_ = new StuckTask(&task_runner_);
      stuck_[i].task_->SignalTimeoutId.connect(this,
                                               &TaskTest::OnTimeoutStuck);
      stuck_[i].timed_out_ = false;
      stuck_[i].xlat_ = stuck_[i].task_->unique_id();
      stuck_[i].task_->set_timeout_seconds(i + 1);
      LOG(LS_INFO) << "Task " << stuck_[i].xlat_ << " created with timeout "
                   << stuck_[i].task_->timeout_seconds();
    }

    for (int i = 0; i < HAPPY_TASK_COUNT; ++i) {
      happy_[i].task_ = new HappyTask(&task_runner_);
      happy_[i].task_->SignalTimeoutId.connect(this,
                                               &TaskTest::OnTimeoutHappy);
      happy_[i].task_->SignalDoneId.connect(this,
                                            &TaskTest::OnDoneHappy);
      happy_[i].timed_out_ = false;
      happy_[i].xlat_ = happy_[i].task_->unique_id();
    }

    // start all the tasks in random order
    int stuck_index = 0;
    int happy_index = 0;
    for (int i = 0; i < STUCK_TASK_COUNT + HAPPY_TASK_COUNT; ++i) {
      if ((stuck_index < STUCK_TASK_COUNT) &&
          (happy_index < HAPPY_TASK_COUNT)) {
        if (rand() % 2 == 1) {
          stuck_[stuck_index++].task_->Start();
        } else {
          happy_[happy_index++].task_->Start();
        }
      } else if (stuck_index < STUCK_TASK_COUNT) {
        stuck_[stuck_index++].task_->Start();
      } else {
        happy_[happy_index++].task_->Start();
      }
    }

    for (int i = 0; i < STUCK_TASK_COUNT; ++i) {
      std::cout << "Stuck task #" << i << " timeout is " <<
          stuck_[i].task_->timeout_seconds() << " at " <<
          stuck_[i].task_->timeout_time() << std::endl;
    }

    // just a little self-check to make sure we started all the tasks
    ASSERT_EQ(STUCK_TASK_COUNT, stuck_index);
    ASSERT_EQ(HAPPY_TASK_COUNT, happy_index);

    // run the unblocked tasks
    LOG(LS_INFO) << "Running tasks";
    task_runner_.RunTasks();

    std::cout << "Start time is " << GetCurrentTime() << std::endl;

    // give all the stuck tasks time to timeout
    for (int i = 0; !task_runner_.AllChildrenDone() && i < STUCK_TASK_COUNT;
         ++i) {
      Thread::Current()->ProcessMessages(1000);
      for (int j = 0; j < HAPPY_TASK_COUNT; ++j) {
        if (happy_[j].task_) {
          happy_[j].task_->Wake();
        }
      }
      LOG(LS_INFO) << "Polling tasks";
      task_runner_.PollTasks();
    }

    // We see occasional test failures here due to the stuck tasks not having
    // timed-out yet, which seems like it should be impossible. To help track
    // this down we have added logging of the timing information, which we send
    // directly to stdout so that we get it in opt builds too.
    std::cout << "End time is " << GetCurrentTime() << std::endl;
  }

  void OnTimeoutStuck(const int id) {
    LOG(LS_INFO) << "Timed out task " << id;

    int i;
    for (i = 0; i < STUCK_TASK_COUNT; ++i) {
      if (stuck_[i].xlat_ == id) {
        stuck_[i].timed_out_ = true;
        stuck_[i].task_ = NULL;
        break;
      }
    }

    // getting a bad ID here is a failure, but let's continue
    // running to see what else might go wrong
    EXPECT_LT(i, STUCK_TASK_COUNT);
  }

  void OnTimeoutHappy(const int id) {
    int i;
    for (i = 0; i < HAPPY_TASK_COUNT; ++i) {
      if (happy_[i].xlat_ == id) {
        happy_[i].timed_out_ = true;
        happy_[i].task_ = NULL;
        break;
      }
    }

    // getting a bad ID here is a failure, but let's continue
    // running to see what else might go wrong
    EXPECT_LT(i, HAPPY_TASK_COUNT);
  }

  void OnDoneHappy(const int id) {
    int i;
    for (i = 0; i < HAPPY_TASK_COUNT; ++i) {
      if (happy_[i].xlat_ == id) {
        happy_[i].task_ = NULL;
        break;
      }
    }

    // getting a bad ID here is a failure, but let's continue
    // running to see what else might go wrong
    EXPECT_LT(i, HAPPY_TASK_COUNT);
  }

  void check_passed() {
    EXPECT_TRUE(task_runner_.AllChildrenDone());

    // make sure none of our happy tasks timed out
    for (int i = 0; i < HAPPY_TASK_COUNT; ++i) {
      EXPECT_FALSE(happy_[i].timed_out_);
    }

    // make sure all of our stuck tasks timed out
    for (int i = 0; i < STUCK_TASK_COUNT; ++i) {
      EXPECT_TRUE(stuck_[i].timed_out_);
      if (!stuck_[i].timed_out_) {
        std::cout << "Stuck task #" << i << " timeout is at "
                  << stuck_[i].task_->timeout_time() << std::endl;
      }
    }

    std::cout.flush();
  }

 private:
  struct TaskInfo {
    IdTimeoutTask *task_;
    bool timed_out_;
    int xlat_;
  };

  MyTaskRunner task_runner_;
  TaskInfo stuck_[STUCK_TASK_COUNT];
  TaskInfo happy_[HAPPY_TASK_COUNT];
};

TEST(start_task_test, Timeout) {
  TaskTest task_test;
  task_test.Start();
  task_test.check_passed();
}

// Test for aborting the task while it is running

class AbortTask : public Task {
 public:
  explicit AbortTask(TaskParent *parent) : Task(parent) {
    set_timeout_seconds(1);
  }

  virtual int ProcessStart() {
    Abort();
    return STATE_NEXT;
  }
 private:
  RTC_DISALLOW_COPY_AND_ASSIGN(AbortTask);
};

class TaskAbortTest : public sigslot::has_slots<> {
 public:
  TaskAbortTest() {}

  // no need to delete any tasks; the task runner owns them
  ~TaskAbortTest() {}

  void Start() {
    Task *abort_task = new AbortTask(&task_runner_);
    abort_task->SignalTimeout.connect(this, &TaskAbortTest::OnTimeout);
    abort_task->Start();

    // run the task
    task_runner_.RunTasks();
  }

 private:
  void OnTimeout() {
    FAIL() << "Task timed out instead of aborting.";
  }

  MyTaskRunner task_runner_;
  RTC_DISALLOW_COPY_AND_ASSIGN(TaskAbortTest);
};

TEST(start_task_test, Abort) {
  TaskAbortTest abort_test;
  abort_test.Start();
}

// Test for aborting a task to verify that it does the Wake operation
// which gets it deleted.

class SetBoolOnDeleteTask : public Task {
 public:
  SetBoolOnDeleteTask(TaskParent *parent, bool *set_when_deleted)
    : Task(parent),
      set_when_deleted_(set_when_deleted) {
    EXPECT_TRUE(NULL != set_when_deleted);
    EXPECT_FALSE(*set_when_deleted);
  }

  virtual ~SetBoolOnDeleteTask() {
    *set_when_deleted_ = true;
  }

  virtual int ProcessStart() {
    return STATE_BLOCKED;
  }

 private:
  bool* set_when_deleted_;
  RTC_DISALLOW_COPY_AND_ASSIGN(SetBoolOnDeleteTask);
};

class AbortShouldWakeTest : public sigslot::has_slots<> {
 public:
  AbortShouldWakeTest() {}

  // no need to delete any tasks; the task runner owns them
  ~AbortShouldWakeTest() {}

  void Start() {
    bool task_deleted = false;
    Task *task_to_abort = new SetBoolOnDeleteTask(&task_runner_, &task_deleted);
    task_to_abort->Start();

    // Task::Abort() should call TaskRunner::WakeTasks(). WakeTasks calls
    // TaskRunner::RunTasks() immediately which should delete the task.
    task_to_abort->Abort();
    EXPECT_TRUE(task_deleted);

    if (!task_deleted) {
      // avoid a crash (due to referencing a local variable)
      // if the test fails.
      task_runner_.RunTasks();
    }
  }

 private:
  void OnTimeout() {
    FAIL() << "Task timed out instead of aborting.";
  }

  MyTaskRunner task_runner_;
  RTC_DISALLOW_COPY_AND_ASSIGN(AbortShouldWakeTest);
};

TEST(start_task_test, AbortShouldWake) {
  AbortShouldWakeTest abort_should_wake_test;
  abort_should_wake_test.Start();
}

// Validate that TaskRunner's OnTimeoutChange gets called appropriately
//  * When a task calls UpdateTaskTimeout
//  * When the next timeout task time, times out
class TimeoutChangeTest : public sigslot::has_slots<> {
 public:
  TimeoutChangeTest()
    : task_count_(ARRAY_SIZE(stuck_tasks_)) {}

  // no need to delete any tasks; the task runner owns them
  ~TimeoutChangeTest() {}

  void Start() {
    for (int i = 0; i < task_count_; ++i) {
      stuck_tasks_[i] = new StuckTask(&task_runner_);
      stuck_tasks_[i]->set_timeout_seconds(i + 2);
      stuck_tasks_[i]->SignalTimeoutId.connect(this,
                                               &TimeoutChangeTest::OnTimeoutId);
    }

    for (int i = task_count_ - 1; i >= 0; --i) {
      stuck_tasks_[i]->Start();
    }
    task_runner_.clear_timeout_change();

    // At this point, our timeouts are set as follows
    // task[0] is 2 seconds, task[1] at 3 seconds, etc.

    stuck_tasks_[0]->set_timeout_seconds(2);
    // Now, task[0] is 2 seconds, task[1] at 3 seconds...
    // so timeout change shouldn't be called.
    EXPECT_FALSE(task_runner_.timeout_change());
    task_runner_.clear_timeout_change();

    stuck_tasks_[0]->set_timeout_seconds(1);
    // task[0] is 1 seconds, task[1] at 3 seconds...
    // The smallest timeout got smaller so timeout change be called.
    EXPECT_TRUE(task_runner_.timeout_change());
    task_runner_.clear_timeout_change();

    stuck_tasks_[1]->set_timeout_seconds(2);
    // task[0] is 1 seconds, task[1] at 2 seconds...
    // The smallest timeout is still 1 second so no timeout change.
    EXPECT_FALSE(task_runner_.timeout_change());
    task_runner_.clear_timeout_change();

    while (task_count_ > 0) {
      int previous_count = task_count_;
      task_runner_.PollTasks();
      if (previous_count != task_count_) {
        // We only get here when a task times out.  When that
        // happens, the timeout change should get called because
        // the smallest timeout is now in the past.
        EXPECT_TRUE(task_runner_.timeout_change());
        task_runner_.clear_timeout_change();
      }
      Thread::Current()->socketserver()->Wait(500, false);
    }
  }

 private:
  void OnTimeoutId(const int id) {
    for (int i = 0; i < ARRAY_SIZE(stuck_tasks_); ++i) {
      if (stuck_tasks_[i] && stuck_tasks_[i]->unique_id() == id) {
        task_count_--;
        stuck_tasks_[i] = NULL;
        break;
      }
    }
  }

  MyTaskRunner task_runner_;
  StuckTask* (stuck_tasks_[3]);
  int task_count_;
  RTC_DISALLOW_COPY_AND_ASSIGN(TimeoutChangeTest);
};

TEST(start_task_test, TimeoutChange) {
  TimeoutChangeTest timeout_change_test;
  timeout_change_test.Start();
}

class DeleteTestTaskRunner : public TaskRunner {
 public:
  DeleteTestTaskRunner() {
  }
  virtual void WakeTasks() { }
  virtual int64_t CurrentTime() { return GetCurrentTime(); }
 private:
  RTC_DISALLOW_COPY_AND_ASSIGN(DeleteTestTaskRunner);
};

TEST(unstarted_task_test, DeleteTask) {
  // This test ensures that we don't
  // crash if a task is deleted without running it.
  DeleteTestTaskRunner task_runner;
  HappyTask* happy_task = new HappyTask(&task_runner);
  happy_task->Start();

  // try deleting the task directly
  HappyTask* child_happy_task = new HappyTask(happy_task);
  delete child_happy_task;

  // run the unblocked tasks
  task_runner.RunTasks();
}

TEST(unstarted_task_test, DoNotDeleteTask1) {
  // This test ensures that we don't
  // crash if a task runner is deleted without
  // running a certain task.
  DeleteTestTaskRunner task_runner;
  HappyTask* happy_task = new HappyTask(&task_runner);
  happy_task->Start();

  HappyTask* child_happy_task = new HappyTask(happy_task);
  child_happy_task->Start();

  // Never run the tasks
}

TEST(unstarted_task_test, DoNotDeleteTask2) {
  // This test ensures that we don't
  // crash if a taskrunner is delete with a
  // task that has never been started.
  DeleteTestTaskRunner task_runner;
  HappyTask* happy_task = new HappyTask(&task_runner);
  happy_task->Start();

  // Do not start the task.
  // Note: this leaks memory, so don't do this.
  // Instead, always run your tasks or delete them.
  new HappyTask(happy_task);

  // run the unblocked tasks
  task_runner.RunTasks();
}

}  // namespace rtc
