text: /*
   *  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
  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
  