// 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 "ppapi/proxy/raw_var_data.h"

#include <stddef.h>
#include <stdint.h>

#include <memory>

#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/shared_impl/array_var.h"
#include "ppapi/shared_impl/dictionary_var.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
#include "ppapi/shared_impl/test_globals.h"
#include "ppapi/shared_impl/test_utils.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ppapi {
namespace proxy {

namespace {

void DefaultHandleWriter(base::Pickle* m, const SerializedHandle& handle) {
  IPC::ParamTraits<SerializedHandle>::Write(m, handle);
}

class RawVarDataTest : public testing::Test {
 public:
  RawVarDataTest() {}
  ~RawVarDataTest() {}

  // testing::Test implementation.
  virtual void SetUp() {
    ProxyLock::Acquire();
  }
  virtual void TearDown() {
    ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
    ProxyLock::Release();
  }

 private:
  base::test::SingleThreadTaskEnvironment
      task_environment_;  // Required to receive callbacks.
  TestGlobals globals_;
};

bool WriteAndRead(const PP_Var& var, PP_Var* result) {
  PP_Instance dummy_instance = 1234;
  std::unique_ptr<RawVarDataGraph> expected_data(
      RawVarDataGraph::Create(var, dummy_instance));
  if (!expected_data)
    return false;
  IPC::Message m;
  expected_data->Write(&m, base::Bind(&DefaultHandleWriter));
  base::PickleIterator iter(m);
  std::unique_ptr<RawVarDataGraph> actual_data(
      RawVarDataGraph::Read(&m, &iter));
  *result = actual_data->CreatePPVar(dummy_instance);
  return true;
}

// Assumes a ref for var.
bool WriteReadAndCompare(const PP_Var& var) {
  ScopedPPVar expected(ScopedPPVar::PassRef(), var);
  PP_Var result;
  bool success = WriteAndRead(expected.get(), &result);
  if (!success)
    return false;
  ScopedPPVar actual(ScopedPPVar::PassRef(), result);
  return TestEqual(expected.get(), actual.get(), true);
}

}  // namespace

TEST_F(RawVarDataTest, SimpleTest) {
  EXPECT_TRUE(WriteReadAndCompare(PP_MakeUndefined()));
  EXPECT_TRUE(WriteReadAndCompare(PP_MakeNull()));
  EXPECT_TRUE(WriteReadAndCompare(PP_MakeInt32(100)));
  EXPECT_TRUE(WriteReadAndCompare(PP_MakeBool(PP_TRUE)));
  EXPECT_TRUE(WriteReadAndCompare(PP_MakeDouble(53.75)));
  PP_Var object;
  object.type = PP_VARTYPE_OBJECT;
  object.value.as_id = 10;
  EXPECT_TRUE(WriteReadAndCompare(object));
}

TEST_F(RawVarDataTest, StringTest) {
  EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("")));
  EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("hello world!")));
}

TEST_F(RawVarDataTest, ArrayBufferTest) {
  std::string data = "hello world!";
  PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
      static_cast<uint32_t>(data.size()), data.data());
  EXPECT_TRUE(WriteReadAndCompare(var));
  var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
      0, static_cast<void*>(NULL));
  EXPECT_TRUE(WriteReadAndCompare(var));
  // TODO(raymes): add tests for shmem type array buffers.
}

TEST_F(RawVarDataTest, DictionaryArrayTest) {
  // Empty array.
  scoped_refptr<ArrayVar> array(new ArrayVar);
  ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar());
  EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));

  size_t index = 0;

  // Array with primitives.
  array->Set(static_cast<uint32_t>(index++), PP_MakeUndefined());
  array->Set(static_cast<uint32_t>(index++), PP_MakeNull());
  array->Set(static_cast<uint32_t>(index++), PP_MakeInt32(100));
  array->Set(static_cast<uint32_t>(index++), PP_MakeBool(PP_FALSE));
  array->Set(static_cast<uint32_t>(index++), PP_MakeDouble(0.123));
  EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));

  // Array with 2 references to the same string.
  ScopedPPVar release_string(
      ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc"));
  array->Set(static_cast<uint32_t>(index++), release_string.get());
  array->Set(static_cast<uint32_t>(index++), release_string.get());
  EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));

  // Array with nested array that references the same string.
  scoped_refptr<ArrayVar> array2(new ArrayVar);
  ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar());
  array2->Set(0, release_string.get());
  array->Set(static_cast<uint32_t>(index++), release_array2.get());
  EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));

  // Empty dictionary.
  scoped_refptr<DictionaryVar> dictionary(new DictionaryVar);
  ScopedPPVar release_dictionary(ScopedPPVar::PassRef(),
                                 dictionary->GetPPVar());
  EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));

  // Dictionary with primitives.
  dictionary->SetWithStringKey("1", PP_MakeUndefined());
  dictionary->SetWithStringKey("2", PP_MakeNull());
  dictionary->SetWithStringKey("3", PP_MakeInt32(-100));
  dictionary->SetWithStringKey("4", PP_MakeBool(PP_TRUE));
  dictionary->SetWithStringKey("5", PP_MakeDouble(-103.52));
  EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));

  // Dictionary with 2 references to the same string.
  dictionary->SetWithStringKey("6", release_string.get());
  dictionary->SetWithStringKey("7", release_string.get());
  EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));

  // Dictionary with nested dictionary that references the same string.
  scoped_refptr<DictionaryVar> dictionary2(new DictionaryVar);
  ScopedPPVar release_dictionary2(ScopedPPVar::PassRef(),
                                  dictionary2->GetPPVar());
  dictionary2->SetWithStringKey("abc", release_string.get());
  dictionary->SetWithStringKey("8", release_dictionary2.get());
  EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));

  // Array with dictionary.
  array->Set(static_cast<uint32_t>(index++), release_dictionary.get());
  EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));

  // Array with dictionary with array.
  array2->Set(0, PP_MakeInt32(100));
  dictionary->SetWithStringKey("9", release_array2.get());
  EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));

  // Array <-> dictionary cycle.
  dictionary->SetWithStringKey("10", release_array.get());
  PP_Var result;
  ASSERT_FALSE(WriteAndRead(release_dictionary.get(), &result));
  // Break the cycle.
  // TODO(raymes): We need some better machinery for releasing vars with
  // cycles. Remove the code below once we have that.
  dictionary->DeleteWithStringKey("10");

  // Array with self references.
  array->Set(static_cast<uint32_t>(index), release_array.get());
  ASSERT_FALSE(WriteAndRead(release_array.get(), &result));
  // Break the self reference.
  array->Set(static_cast<uint32_t>(index), PP_MakeUndefined());
}

TEST_F(RawVarDataTest, ResourceTest) {
  // TODO(mgiuca): This test passes trivially, since GetVarTracker() returns a
  // TestVarTracker which returns a null PP_Var.
  ScopedPPVar resource(
      ScopedPPVar::PassRef(),
      PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVar(34));
  EXPECT_TRUE(WriteReadAndCompare(resource.get()));

  // TODO(mgiuca): Test a host resource with an IPC::Message. It is currently a
  // checkfail to deserialize such a resource.
}

}  // namespace proxy
}  // namespace ppapi
