/*
 *  Copyright 2013 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 "webrtc/api/proxy.h"

#include <memory>
#include <string>

#include "testing/gmock/include/gmock/gmock.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/thread.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::Exactly;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;

namespace webrtc {

// Interface used for testing here.
class FakeInterface : public rtc::RefCountInterface {
 public:
  virtual void VoidMethod0() = 0;
  virtual std::string Method0() = 0;
  virtual std::string ConstMethod0() const = 0;
  virtual std::string Method1(std::string s) = 0;
  virtual std::string ConstMethod1(std::string s) const = 0;
  virtual std::string Method2(std::string s1, std::string s2) = 0;

 protected:
  ~FakeInterface() {}
};

// Implementation of the test interface.
class Fake : public FakeInterface {
 public:
  static rtc::scoped_refptr<Fake> Create() {
    return new rtc::RefCountedObject<Fake>();
  }

  MOCK_METHOD0(VoidMethod0, void());
  MOCK_METHOD0(Method0, std::string());
  MOCK_CONST_METHOD0(ConstMethod0, std::string());

  MOCK_METHOD1(Method1, std::string(std::string));
  MOCK_CONST_METHOD1(ConstMethod1, std::string(std::string));

  MOCK_METHOD2(Method2, std::string(std::string, std::string));

 protected:
  Fake() {}
  ~Fake() {}
};

// Proxies for the test interface.
BEGIN_PROXY_MAP(Fake)
  PROXY_METHOD0(void, VoidMethod0)
  PROXY_METHOD0(std::string, Method0)
  PROXY_CONSTMETHOD0(std::string, ConstMethod0)
  PROXY_WORKER_METHOD1(std::string, Method1, std::string)
  PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string)
  PROXY_WORKER_METHOD2(std::string, Method2, std::string, std::string)
END_PROXY()

// Preprocessor hack to get a proxy class a name different than FakeProxy.
#define FakeProxy FakeSignalingProxy
#define FakeProxyWithInternal FakeSignalingProxyWithInternal
BEGIN_SIGNALING_PROXY_MAP(Fake)
  PROXY_METHOD0(void, VoidMethod0)
  PROXY_METHOD0(std::string, Method0)
  PROXY_CONSTMETHOD0(std::string, ConstMethod0)
  PROXY_METHOD1(std::string, Method1, std::string)
  PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string)
  PROXY_METHOD2(std::string, Method2, std::string, std::string)
END_SIGNALING_PROXY()
#undef FakeProxy

class SignalingProxyTest : public testing::Test {
 public:
  // Checks that the functions are called on the right thread.
  void CheckSignalingThread() { EXPECT_TRUE(signaling_thread_->IsCurrent()); }

 protected:
  void SetUp() override {
    signaling_thread_.reset(new rtc::Thread());
    ASSERT_TRUE(signaling_thread_->Start());
    fake_ = Fake::Create();
    fake_signaling_proxy_ =
        FakeSignalingProxy::Create(signaling_thread_.get(), fake_.get());
  }

 protected:
  std::unique_ptr<rtc::Thread> signaling_thread_;
  rtc::scoped_refptr<FakeInterface> fake_signaling_proxy_;
  rtc::scoped_refptr<Fake> fake_;
};

TEST_F(SignalingProxyTest, VoidMethod0) {
  EXPECT_CALL(*fake_, VoidMethod0())
      .Times(Exactly(1))
      .WillOnce(
          InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread));
  fake_signaling_proxy_->VoidMethod0();
}

TEST_F(SignalingProxyTest, Method0) {
  EXPECT_CALL(*fake_, Method0())
      .Times(Exactly(1))
      .WillOnce(DoAll(
          InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
          Return("Method0")));
  EXPECT_EQ("Method0", fake_signaling_proxy_->Method0());
}

TEST_F(SignalingProxyTest, ConstMethod0) {
  EXPECT_CALL(*fake_, ConstMethod0())
      .Times(Exactly(1))
      .WillOnce(DoAll(
          InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
          Return("ConstMethod0")));
  EXPECT_EQ("ConstMethod0", fake_signaling_proxy_->ConstMethod0());
}

TEST_F(SignalingProxyTest, Method1) {
  const std::string arg1 = "arg1";
  EXPECT_CALL(*fake_, Method1(arg1))
      .Times(Exactly(1))
      .WillOnce(DoAll(
          InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
          Return("Method1")));
  EXPECT_EQ("Method1", fake_signaling_proxy_->Method1(arg1));
}

TEST_F(SignalingProxyTest, ConstMethod1) {
  const std::string arg1 = "arg1";
  EXPECT_CALL(*fake_, ConstMethod1(arg1))
      .Times(Exactly(1))
      .WillOnce(DoAll(
          InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
          Return("ConstMethod1")));
  EXPECT_EQ("ConstMethod1", fake_signaling_proxy_->ConstMethod1(arg1));
}

TEST_F(SignalingProxyTest, Method2) {
  const std::string arg1 = "arg1";
  const std::string arg2 = "arg2";
  EXPECT_CALL(*fake_, Method2(arg1, arg2))
      .Times(Exactly(1))
      .WillOnce(DoAll(
          InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread),
          Return("Method2")));
  EXPECT_EQ("Method2", fake_signaling_proxy_->Method2(arg1, arg2));
}

class ProxyTest : public SignalingProxyTest {
 public:
  // Checks that the functions are called on the right thread.
  void CheckWorkerThread() { EXPECT_TRUE(worker_thread_->IsCurrent()); }

 protected:
  void SetUp() override {
    SignalingProxyTest::SetUp();
    worker_thread_.reset(new rtc::Thread());
    ASSERT_TRUE(worker_thread_->Start());
    fake_proxy_ = FakeProxy::Create(signaling_thread_.get(),
                                    worker_thread_.get(), fake_.get());
  }

 protected:
  std::unique_ptr<rtc::Thread> worker_thread_;
  rtc::scoped_refptr<FakeInterface> fake_proxy_;
};

TEST_F(ProxyTest, VoidMethod0) {
  EXPECT_CALL(*fake_, VoidMethod0())
      .Times(Exactly(1))
      .WillOnce(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread));
  fake_proxy_->VoidMethod0();
}

TEST_F(ProxyTest, Method0) {
  EXPECT_CALL(*fake_, Method0())
      .Times(Exactly(1))
      .WillOnce(
          DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread),
                Return("Method0")));
  EXPECT_EQ("Method0",
            fake_proxy_->Method0());
}

TEST_F(ProxyTest, ConstMethod0) {
  EXPECT_CALL(*fake_, ConstMethod0())
      .Times(Exactly(1))
      .WillOnce(
          DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread),
                Return("ConstMethod0")));
  EXPECT_EQ("ConstMethod0",
            fake_proxy_->ConstMethod0());
}

TEST_F(ProxyTest, WorkerMethod1) {
  const std::string arg1 = "arg1";
  EXPECT_CALL(*fake_, Method1(arg1))
      .Times(Exactly(1))
      .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckWorkerThread),
                      Return("Method1")));
  EXPECT_EQ("Method1", fake_proxy_->Method1(arg1));
}

TEST_F(ProxyTest, ConstMethod1) {
  const std::string arg1 = "arg1";
  EXPECT_CALL(*fake_, ConstMethod1(arg1))
      .Times(Exactly(1))
      .WillOnce(
          DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckSignalingThread),
                Return("ConstMethod1")));
  EXPECT_EQ("ConstMethod1", fake_proxy_->ConstMethod1(arg1));
}

TEST_F(ProxyTest, WorkerMethod2) {
  const std::string arg1 = "arg1";
  const std::string arg2 = "arg2";
  EXPECT_CALL(*fake_, Method2(arg1, arg2))
      .Times(Exactly(1))
      .WillOnce(DoAll(InvokeWithoutArgs(this, &ProxyTest::CheckWorkerThread),
                      Return("Method2")));
  EXPECT_EQ("Method2", fake_proxy_->Method2(arg1, arg2));
}

}  // namespace webrtc
