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

#include <cstring>

#include "base/synchronization/waitable_event.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppp_messaging.h"
#include "ppapi/proxy/ppapi_proxy_test.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/var.h"

namespace ppapi {
namespace proxy {

namespace {

// This is a poor man's mock of PPP_Messaging using global variables. Eventually
// we should generalize making PPAPI interface mocks by using IDL or macro/
// template magic.
PP_Instance received_instance;
PP_Var received_var;
base::WaitableEvent handle_message_called(false, false);

void HandleMessage(PP_Instance instance, PP_Var message_data) {
  received_instance = instance;
  received_var = message_data;
  handle_message_called.Signal();
}

// Clear all the 'received' values for our mock.  Call this before you expect
// one of the functions to be invoked.
void ResetReceived() {
  received_instance = 0;
  received_var.type = PP_VARTYPE_UNDEFINED;
  received_var.value.as_id = 0;
}

PPP_Messaging ppp_messaging_mock = {
  &HandleMessage
};

class PPP_Messaging_ProxyTest : public TwoWayTest {
 public:
  PPP_Messaging_ProxyTest()
      : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
    plugin().RegisterTestInterface(PPP_MESSAGING_INTERFACE,
                                   &ppp_messaging_mock);
  }
};

void CompareAndReleaseStringVar(PluginProxyTestHarness* plugin_harness,
                                PP_Var received_var,
                                const std::string& test_string) {
  ProxyAutoLock lock;
  Var* received_string = plugin_harness->var_tracker().GetVar(received_var);
  ASSERT_TRUE(received_string);
  ASSERT_TRUE(received_string->AsStringVar());
  EXPECT_EQ(test_string, received_string->AsStringVar()->value());
  // Now release the var, and the string should go away (because the ref
  // count should be one).
  plugin_harness->var_tracker().ReleaseVar(received_var);
  EXPECT_FALSE(StringVar::FromPPVar(received_var));
}

}  // namespace

TEST_F(PPP_Messaging_ProxyTest, SendMessages) {
  // Grab the host-side proxy of ppp_messaging.
  const PPP_Messaging* ppp_messaging = static_cast<const PPP_Messaging*>(
      host().host_dispatcher()->GetProxiedInterface(
          PPP_MESSAGING_INTERFACE));

  PP_Instance expected_instance = pp_instance();
  PP_Var expected_var = PP_MakeUndefined();
  ResetReceived();
  ppp_messaging->HandleMessage(expected_instance, expected_var);
  handle_message_called.Wait();
  EXPECT_EQ(expected_instance, received_instance);
  EXPECT_EQ(expected_var.type, received_var.type);

  expected_var = PP_MakeNull();
  ResetReceived();
  ppp_messaging->HandleMessage(expected_instance, expected_var);
  handle_message_called.Wait();
  EXPECT_EQ(expected_instance, received_instance);
  EXPECT_EQ(expected_var.type, received_var.type);

  expected_var = PP_MakeBool(PP_TRUE);
  ResetReceived();
  ppp_messaging->HandleMessage(expected_instance, expected_var);
  handle_message_called.Wait();
  EXPECT_EQ(expected_instance, received_instance);
  EXPECT_EQ(expected_var.type, received_var.type);
  EXPECT_EQ(expected_var.value.as_bool, received_var.value.as_bool);

  expected_var = PP_MakeInt32(12345);
  ResetReceived();
  ppp_messaging->HandleMessage(expected_instance, expected_var);
  handle_message_called.Wait();
  EXPECT_EQ(expected_instance, received_instance);
  EXPECT_EQ(expected_var.type, received_var.type);
  EXPECT_EQ(expected_var.value.as_int, received_var.value.as_int);

  expected_var = PP_MakeDouble(3.1415);
  ResetReceived();
  ppp_messaging->HandleMessage(expected_instance, expected_var);
  handle_message_called.Wait();
  EXPECT_EQ(expected_instance, received_instance);
  EXPECT_EQ(expected_var.type, received_var.type);
  EXPECT_EQ(expected_var.value.as_double, received_var.value.as_double);

  const std::string kTestString("Hello world!");
  expected_var = StringVar::StringToPPVar(kTestString);
  ResetReceived();
  ppp_messaging->HandleMessage(expected_instance, expected_var);
  // Now release the var, and the string should go away (because the ref
  // count should be one).
  host().var_tracker().ReleaseVar(expected_var);
  EXPECT_FALSE(StringVar::FromPPVar(expected_var));

  handle_message_called.Wait();
  EXPECT_EQ(expected_instance, received_instance);
  EXPECT_EQ(expected_var.type, received_var.type);
  PostTaskOnRemoteHarness(
      base::Bind(CompareAndReleaseStringVar,
                 &plugin(),
                 received_var,
                 kTestString));
}

}  // namespace proxy
}  // namespace ppapi

