/*
 *  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.
 */

#include <memory>

#include "rtc_base/constructor_magic.h"
#include "rtc_base/gunit.h"
#include "rtc_base/signal_thread.h"
#include "rtc_base/socket_server.h"
#include "rtc_base/thread.h"
#include "test/gtest.h"

namespace rtc {
namespace {

// 10 seconds.
static const int kTimeout = 10000;

class SignalThreadTest : public testing::Test, public sigslot::has_slots<> {
 public:
  class SlowSignalThread : public SignalThread {
   public:
    SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {}

    ~SlowSignalThread() override {
      EXPECT_EQ(harness_->main_thread_, Thread::Current());
      ++harness_->thread_deleted_;
    }

    const SignalThreadTest* harness() { return harness_; }

   protected:
    void OnWorkStart() override {
      ASSERT_TRUE(harness_ != nullptr);
      ++harness_->thread_started_;
      EXPECT_EQ(harness_->main_thread_, Thread::Current());
      EXPECT_FALSE(worker()->RunningForTest());  // not started yet
    }

    void OnWorkStop() override {
      ++harness_->thread_stopped_;
      EXPECT_EQ(harness_->main_thread_, Thread::Current());
      EXPECT_TRUE(worker()->RunningForTest());  // not stopped yet
    }

    void OnWorkDone() override {
      ++harness_->thread_done_;
      EXPECT_EQ(harness_->main_thread_, Thread::Current());
      EXPECT_TRUE(worker()->RunningForTest());  // not stopped yet
    }

    void DoWork() override {
      EXPECT_NE(harness_->main_thread_, Thread::Current());
      EXPECT_EQ(worker(), Thread::Current());
      Thread::Current()->socketserver()->Wait(250, false);
    }

   private:
    SignalThreadTest* harness_;
    RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
  };

  void OnWorkComplete(rtc::SignalThread* thread) {
    SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
    EXPECT_EQ(t->harness(), this);
    EXPECT_EQ(main_thread_, Thread::Current());

    ++thread_completed_;
    if (!called_release_) {
      thread->Release();
    }
  }

  void SetUp() override {
    main_thread_ = Thread::Current();
    thread_ = new SlowSignalThread(this);
    thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
    called_release_ = false;
    thread_started_ = 0;
    thread_done_ = 0;
    thread_completed_ = 0;
    thread_stopped_ = 0;
    thread_deleted_ = 0;
  }

  void ExpectState(int started,
                   int done,
                   int completed,
                   int stopped,
                   int deleted) {
    EXPECT_EQ(started, thread_started_);
    EXPECT_EQ(done, thread_done_);
    EXPECT_EQ(completed, thread_completed_);
    EXPECT_EQ(stopped, thread_stopped_);
    EXPECT_EQ(deleted, thread_deleted_);
  }

  void ExpectStateWait(int started,
                       int done,
                       int completed,
                       int stopped,
                       int deleted,
                       int timeout) {
    EXPECT_EQ_WAIT(started, thread_started_, timeout);
    EXPECT_EQ_WAIT(done, thread_done_, timeout);
    EXPECT_EQ_WAIT(completed, thread_completed_, timeout);
    EXPECT_EQ_WAIT(stopped, thread_stopped_, timeout);
    EXPECT_EQ_WAIT(deleted, thread_deleted_, timeout);
  }

  Thread* main_thread_;
  SlowSignalThread* thread_;
  bool called_release_;

  int thread_started_;
  int thread_done_;
  int thread_completed_;
  int thread_stopped_;
  int thread_deleted_;
};

class OwnerThread : public Thread, public sigslot::has_slots<> {
 public:
  explicit OwnerThread(SignalThreadTest* harness)
      : harness_(harness), has_run_(false) {}

  ~OwnerThread() override { Stop(); }

  void Run() override {
    SignalThreadTest::SlowSignalThread* signal_thread =
        new SignalThreadTest::SlowSignalThread(harness_);
    signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
    signal_thread->Start();
    Thread::Current()->socketserver()->Wait(100, false);
    signal_thread->Release();
    // Delete |signal_thread|.
    signal_thread->Destroy(true);
    has_run_ = true;
  }

  bool has_run() { return has_run_; }
  void OnWorkDone(SignalThread* signal_thread) {
    FAIL() << " This shouldn't get called.";
  }

 private:
  SignalThreadTest* harness_;
  bool has_run_;
  RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
};

// Test for when the main thread goes away while the
// signal thread is still working.  This may happen
// when shutting down the process.
TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
  // We don't use |thread_| for this test, so destroy it.
  thread_->Destroy(true);

  {
    std::unique_ptr<OwnerThread> owner(new OwnerThread(this));
    main_thread_ = owner.get();
    owner->Start();
    while (!owner->has_run()) {
      Thread::Current()->socketserver()->Wait(10, false);
    }
  }
  // At this point the main thread has gone away.
  // Give the SignalThread a little time to do its callback,
  // which will crash if the signal thread doesn't handle
  // this situation well.
  Thread::Current()->socketserver()->Wait(500, false);
}

TEST_F(SignalThreadTest, ThreadFinishes) {
  thread_->Start();
  ExpectState(1, 0, 0, 0, 0);
  ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
}

TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
  thread_->Start();
  ExpectState(1, 0, 0, 0, 0);
  thread_->Release();
  called_release_ = true;
  ExpectState(1, 0, 0, 0, 0);
  ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
}

TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
  thread_->Start();
  ExpectState(1, 0, 0, 0, 0);
  thread_->Destroy(true);
  ExpectState(1, 0, 0, 1, 1);
  Thread::Current()->ProcessMessages(0);
  ExpectState(1, 0, 0, 1, 1);
}

TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
  thread_->Start();
  ExpectState(1, 0, 0, 0, 0);
  thread_->Destroy(false);
  ExpectState(1, 0, 0, 1, 0);
  ExpectStateWait(1, 1, 0, 1, 1, kTimeout);
}

}  // namespace
}  // namespace rtc
