// Copyright (c) 2012 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 PPAPI_PROXY_PPAPI_PROXY_TEST_H_
#define PPAPI_PROXY_PPAPI_PROXY_TEST_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <string>

#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/task_environment.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/plugin_proxy_delegate.h"
#include "ppapi/proxy/plugin_resource_tracker.h"
#include "ppapi/proxy/plugin_var_tracker.h"
#include "ppapi/proxy/resource_message_test_sink.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/test_globals.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
class RunLoop;
class SingleThreadTaskRunner;
}

namespace ppapi {
namespace proxy {

class MessageLoopResource;

// Base class for plugin and host test harnesses. Tests will not use this
// directly. Instead, use the PluginProxyTest, HostProxyTest, or TwoWayTest.
class ProxyTestHarnessBase {
 public:
  enum GlobalsConfiguration {
    PER_THREAD_GLOBALS,
    SINGLETON_GLOBALS
  };

  ProxyTestHarnessBase();
  virtual ~ProxyTestHarnessBase();

  PP_Module pp_module() const { return pp_module_; }
  PP_Instance pp_instance() const { return pp_instance_; }
  ResourceMessageTestSink& sink() { return sink_; }

  virtual PpapiGlobals* GetGlobals() = 0;
  // Returns either the plugin or host dispatcher, depending on the test.
  virtual Dispatcher* GetDispatcher() = 0;

  // Set up the harness using an IPC::TestSink to capture messages.
  virtual void SetUpHarness() = 0;

  // Set up the harness using a real IPC channel.
  virtual void SetUpHarnessWithChannel(
      const IPC::ChannelHandle& channel_handle,
      base::SingleThreadTaskRunner* ipc_task_runner,
      base::WaitableEvent* shutdown_event,
      bool is_client) = 0;

  virtual void TearDownHarness() = 0;

  // Implementation of GetInterface for the dispatcher. This will
  // return NULL for all interfaces unless one is registered by calling
  // RegisterTestInterface();
  const void* GetInterface(const char* name);

  // Allows the test to specify an interface implementation for a given
  // interface name. This will be returned when any of the proxy logic
  // requests a local interface.
  void RegisterTestInterface(const char* name, const void* test_interface);

  // Sends a "supports interface" message to the current dispatcher and returns
  // true if it's supported. This is just for the convenience of tests.
  bool SupportsInterface(const char* name);

 private:
  // Destination for IPC messages sent by the test.
  ResourceMessageTestSink sink_;

  // The module and instance ID associated with the plugin dispatcher.
  PP_Module pp_module_;
  PP_Instance pp_instance_;

  // Stores the data for GetInterface/RegisterTestInterface.
  std::map<std::string, const void*> registered_interfaces_;
};

// Test harness for the plugin side of the proxy.
class PluginProxyTestHarness : public ProxyTestHarnessBase {
 public:
  explicit PluginProxyTestHarness(GlobalsConfiguration globals_config);
  virtual ~PluginProxyTestHarness();

  PluginDispatcher* plugin_dispatcher() { return plugin_dispatcher_.get(); }
  PluginResourceTracker& resource_tracker() {
    return *plugin_globals_->plugin_resource_tracker();
  }
  PluginVarTracker& var_tracker() {
    return *plugin_globals_->plugin_var_tracker();
  }

  // ProxyTestHarnessBase implementation.
  virtual PpapiGlobals* GetGlobals();
  virtual Dispatcher* GetDispatcher();
  virtual void SetUpHarness();
  virtual void SetUpHarnessWithChannel(
      const IPC::ChannelHandle& channel_handle,
      base::SingleThreadTaskRunner* ipc_task_runner,
      base::WaitableEvent* shutdown_event,
      bool is_client);
  virtual void TearDownHarness();

  class PluginDelegateMock : public PluginDispatcher::PluginDelegate,
                             public PluginProxyDelegate {
   public:
    PluginDelegateMock() : ipc_task_runner_(NULL), shutdown_event_() {}

    PluginDelegateMock(const PluginDelegateMock&) = delete;
    PluginDelegateMock& operator=(const PluginDelegateMock&) = delete;

    ~PluginDelegateMock() override {}

    void Init(base::SingleThreadTaskRunner* ipc_task_runner,
              base::WaitableEvent* shutdown_event) {
      ipc_task_runner_ = ipc_task_runner;
      shutdown_event_ = shutdown_event;
    }

    void set_browser_sender(IPC::Sender* browser_sender) {
      browser_sender_ = browser_sender;
    }

    // ProxyChannel::Delegate implementation.
    base::SingleThreadTaskRunner* GetIPCTaskRunner() override;
    base::WaitableEvent* GetShutdownEvent() override;
    IPC::PlatformFileForTransit ShareHandleWithRemote(
        base::PlatformFile handle,
        base::ProcessId remote_pid,
        bool should_close_source) override;
    base::UnsafeSharedMemoryRegion ShareUnsafeSharedMemoryRegionWithRemote(
        const base::UnsafeSharedMemoryRegion& region,
        base::ProcessId remote_pid) override;
    base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote(
        const base::ReadOnlySharedMemoryRegion& region,
        base::ProcessId remote_pid) override;

    // PluginDispatcher::PluginDelegate implementation.
    std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override;
    uint32_t Register(PluginDispatcher* plugin_dispatcher) override;
    void Unregister(uint32_t plugin_dispatcher_id) override;

    // PluginProxyDelegate implementation.
    IPC::Sender* GetBrowserSender() override;
    std::string GetUILanguage() override;
    void SetActiveURL(const std::string& url) override;
    PP_Resource CreateBrowserFont(
        Connection connection,
        PP_Instance instance,
        const PP_BrowserFont_Trusted_Description& desc,
        const Preferences& prefs) override;

   private:
    base::SingleThreadTaskRunner* ipc_task_runner_;  // Weak
    base::WaitableEvent* shutdown_event_;  // Weak
    std::set<PP_Instance> instance_id_set_;
    IPC::Sender* browser_sender_;
  };

 private:
  void CreatePluginGlobals(
      const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner);

  GlobalsConfiguration globals_config_;
  std::unique_ptr<PluginGlobals> plugin_globals_;

  std::unique_ptr<PluginDispatcher> plugin_dispatcher_;
  PluginDelegateMock plugin_delegate_mock_;
};

class PluginProxyTest : public PluginProxyTestHarness, public testing::Test {
 public:
  PluginProxyTest();
  virtual ~PluginProxyTest();

  // testing::Test implementation.
  virtual void SetUp();
  virtual void TearDown();
 private:
  base::test::SingleThreadTaskEnvironment task_environment_;
};

// This class provides support for multi-thread testing. A secondary thread is
// created with a Pepper message loop.
// Subclasses need to implement the two SetUpTestOn*Thread() methods to do the
// actual testing work; and call both PostQuitFor*Thread() when testing is
// done.
class PluginProxyMultiThreadTest
    : public PluginProxyTest,
      public base::DelegateSimpleThread::Delegate {
 public:
  PluginProxyMultiThreadTest();
  ~PluginProxyMultiThreadTest() override;

  // Called before the secondary thread is started, but after all the member
  // variables, including |secondary_thread_| and
  // |secondary_thread_message_loop_|, are initialized.
  virtual void SetUpTestOnMainThread() = 0;

  virtual void SetUpTestOnSecondaryThread() = 0;

  // TEST_F() should call this method.
  void RunTest();

  enum ThreadType {
    MAIN_THREAD,
    SECONDARY_THREAD
  };
  void CheckOnThread(ThreadType thread_type);

  // These can be called on any thread.
  void PostQuitForMainThread();
  void PostQuitForSecondaryThread();

 protected:
  scoped_refptr<MessageLoopResource> secondary_thread_message_loop_;
  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;

 private:
  // base::DelegateSimpleThread::Delegate implementation.
  void Run() override;

  void QuitNestedLoop();

  static void InternalSetUpTestOnSecondaryThread(void* user_data,
                                                 int32_t result);

  std::unique_ptr<base::DelegateSimpleThread> secondary_thread_;
  std::unique_ptr<base::RunLoop> nested_main_thread_message_loop_;
};

class HostProxyTestHarness : public ProxyTestHarnessBase {
 public:
  explicit HostProxyTestHarness(GlobalsConfiguration globals_config);
  virtual ~HostProxyTestHarness();

  HostDispatcher* host_dispatcher() { return host_dispatcher_.get(); }
  ResourceTracker& resource_tracker() {
    return *host_globals_->GetResourceTracker();
  }
  VarTracker& var_tracker() {
    return *host_globals_->GetVarTracker();
  }

  // ProxyTestBase implementation.
  virtual PpapiGlobals* GetGlobals();
  virtual Dispatcher* GetDispatcher();
  virtual void SetUpHarness();
  virtual void SetUpHarnessWithChannel(
      const IPC::ChannelHandle& channel_handle,
      base::SingleThreadTaskRunner* ipc_task_runner,
      base::WaitableEvent* shutdown_event,
      bool is_client);
  virtual void TearDownHarness();

  class DelegateMock : public ProxyChannel::Delegate {
   public:
    DelegateMock() : ipc_task_runner_(NULL), shutdown_event_(NULL) {}

    DelegateMock(const DelegateMock&) = delete;
    DelegateMock& operator=(const DelegateMock&) = delete;

    ~DelegateMock() override {}

    void Init(base::SingleThreadTaskRunner* ipc_task_runner,
              base::WaitableEvent* shutdown_event) {
      ipc_task_runner_ = ipc_task_runner;
      shutdown_event_ = shutdown_event;
    }

    // ProxyChannel::Delegate implementation.
    base::SingleThreadTaskRunner* GetIPCTaskRunner() override;
    base::WaitableEvent* GetShutdownEvent() override;
    IPC::PlatformFileForTransit ShareHandleWithRemote(
        base::PlatformFile handle,
        base::ProcessId remote_pid,
        bool should_close_source) override;
    base::UnsafeSharedMemoryRegion ShareUnsafeSharedMemoryRegionWithRemote(
        const base::UnsafeSharedMemoryRegion& region,
        base::ProcessId remote_pid) override;
    base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote(
        const base::ReadOnlySharedMemoryRegion& region,
        base::ProcessId remote_pid) override;

   private:
    base::SingleThreadTaskRunner* ipc_task_runner_;  // Weak
    base::WaitableEvent* shutdown_event_;  // Weak
  };

 private:
  void CreateHostGlobals();

  GlobalsConfiguration globals_config_;
  std::unique_ptr<ppapi::TestGlobals> host_globals_;
  std::unique_ptr<HostDispatcher> host_dispatcher_;
  // The host side of the real proxy doesn't lock, so this disables locking for
  // the thread the host side of the test runs on.
  std::unique_ptr<ProxyLock::LockingDisablerForTest> disable_locking_;
  DelegateMock delegate_mock_;
};

class HostProxyTest : public HostProxyTestHarness, public testing::Test {
 public:
  HostProxyTest();
  virtual ~HostProxyTest();

  // testing::Test implementation.
  virtual void SetUp();
  virtual void TearDown();
 private:
  base::test::SingleThreadTaskEnvironment task_environment_;
};

// Use this base class to test both sides of a proxy.
class TwoWayTest : public testing::Test {
 public:
  enum TwoWayTestMode {
    TEST_PPP_INTERFACE,
    TEST_PPB_INTERFACE
  };
  TwoWayTest(TwoWayTestMode test_mode);
  virtual ~TwoWayTest();

  HostProxyTestHarness& host() { return host_; }
  PluginProxyTestHarness& plugin() { return plugin_; }
  PP_Module pp_module() const { return host_.pp_module(); }
  PP_Instance pp_instance() const { return host_.pp_instance(); }
  TwoWayTestMode test_mode() { return test_mode_; }

  // testing::Test implementation.
  virtual void SetUp();
  virtual void TearDown();

 protected:
  // Post a task to the thread where the remote harness lives. This
  // is typically used to test the state of the var tracker on the plugin
  // thread. This runs the task synchronously for convenience.
  void PostTaskOnRemoteHarness(base::OnceClosure task);

 private:
  TwoWayTestMode test_mode_;
  HostProxyTestHarness host_;
  PluginProxyTestHarness plugin_;
  // In order to use sync IPC, we need to have an IO thread.
  base::Thread io_thread_;
  // The plugin side of the proxy runs on its own thread.
  base::Thread plugin_thread_;
  // The message loop for the main (host) thread.
  base::test::SingleThreadTaskEnvironment task_environment_;

  // Aliases for the host and plugin harnesses; if we're testing a PPP
  // interface, remote_harness will point to plugin_, and local_harness
  // will point to host_.  This makes it convenient when we're starting and
  // stopping the harnesses.
  ProxyTestHarnessBase* remote_harness_;
  ProxyTestHarnessBase* local_harness_;

  base::WaitableEvent channel_created_;
  base::WaitableEvent shutdown_event_;
};

// Used during Gtests when you have a PP_Var that you want to EXPECT is equal
// to a certain constant string value:
//
//   EXPECT_VAR_IS_STRING("foo", my_var);
#define EXPECT_VAR_IS_STRING(str, var) { \
  StringVar* sv = StringVar::FromPPVar(var); \
  EXPECT_TRUE(sv); \
  if (sv) \
    EXPECT_EQ(str, sv->value()); \
}

}  // namespace proxy
}  // namespace ppapi

#endif  // PPAPI_PROXY_PPAPI_PROXY_TEST_H_
