v8_value_converter_impl_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/values_test_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/v8_value_converter_impl.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To improve the performance of
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// V8ValueConverterImpl::UpdateAndCheckUniqueness, identity hashes of objects
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// are used during checking for duplicates. For testing purposes we need to
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ignore the hash sometimes. Create this helper object to avoid using identity
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// hashes for the lifetime of the helper.
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ScopedAvoidIdentityHashForTesting {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The hashes will be ignored in |converter|, which must not be NULL and it
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // must outlive the created instance of this helper.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit ScopedAvoidIdentityHashForTesting(
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::V8ValueConverterImpl* converter);
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~ScopedAvoidIdentityHashForTesting();
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::V8ValueConverterImpl* converter_;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedAvoidIdentityHashForTesting);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedAvoidIdentityHashForTesting::ScopedAvoidIdentityHashForTesting(
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::V8ValueConverterImpl* converter)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : converter_(converter) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(converter_);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  converter_->avoid_identity_hash_for_testing_ = true;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedAvoidIdentityHashForTesting::~ScopedAvoidIdentityHashForTesting() {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  converter_->avoid_identity_hash_for_testing_ = false;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class V8ValueConverterImplTest : public testing::Test {
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  V8ValueConverterImplTest()
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : isolate_(v8::Isolate::GetCurrent()) {
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    v8::HandleScope handle_scope(isolate_);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    context_.Dispose();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string GetString(base::DictionaryValue* value, const std::string& key) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string temp;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->GetString(key, &temp)) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetString(v8::Handle<v8::Object> value, const std::string& key) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::String> temp =
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value->Get(v8::String::New(key.c_str())).As<v8::String>();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (temp.IsEmpty()) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::String::Utf8Value utf8(temp);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string(*utf8, utf8.length());
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string GetString(base::ListValue* value, uint32 index) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string temp;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->GetString(static_cast<size_t>(index), &temp)) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetString(v8::Handle<v8::Array> value, uint32 index) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::String> temp = value->Get(index).As<v8::String>();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (temp.IsEmpty()) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return std::string();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::String::Utf8Value utf8(temp);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string(*utf8, utf8.length());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsNull(base::DictionaryValue* value, const std::string& key) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* child = NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->Get(key, &child)) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return child->GetType() == base::Value::TYPE_NULL;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsNull(v8::Handle<v8::Object> value, const std::string& key) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Value> child = value->Get(v8::String::New(key.c_str()));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child.IsEmpty()) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return child->IsNull();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsNull(base::ListValue* value, uint32 index) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* child = NULL;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->Get(static_cast<size_t>(index), &child)) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return child->GetType() == base::Value::TYPE_NULL;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsNull(v8::Handle<v8::Array> value, uint32 index) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Value> child = value->Get(index);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child.IsEmpty()) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ADD_FAILURE();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return child->IsNull();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestWeirdType(const V8ValueConverterImpl& converter,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     v8::Handle<v8::Value> val,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Value::Type expected_type,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     scoped_ptr<base::Value> expected_value) {
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    v8::Local<v8::Context> context =
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, context_);
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<base::Value> raw(converter.FromV8Value(val, context));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (expected_value) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(raw.get());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(expected_value->Equals(raw.get()));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_type, raw->GetType());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(raw.get());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Object> object(v8::Object::New());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    object->Set(v8::String::New("test"), val);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> dictionary(
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<base::DictionaryValue*>(
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            converter.FromV8Value(object, context)));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(dictionary.get());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (expected_value) {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Value* temp = NULL;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(dictionary->Get("test", &temp));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_type, temp->GetType());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(expected_value->Equals(temp));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(dictionary->HasKey("test"));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Array> array(v8::Array::New());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array->Set(0, val);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::ListValue> list(
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(list.get());
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (expected_value) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Value* temp = NULL;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(list->Get(0, &temp));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(expected_type, temp->GetType());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(expected_value->Equals(temp));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Arrays should preserve their length, and convert unconvertible
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // types into null.
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Value* temp = NULL;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(list->Get(0, &temp));
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(base::Value::TYPE_NULL, temp->GetType());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Isolate* isolate_;
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Context for the JavaScript in the test.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Persistent<v8::Context> context_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> original_root = base::test::ParseJson(
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{ \n"
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"null\": null, \n"
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"true\": true, \n"
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"false\": false, \n"
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"positive-int\": 42, \n"
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"negative-int\": -42, \n"
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"zero\": 0, \n"
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"double\": 88.8, \n"
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"big-integral-double\": 9007199254740992.0, \n"  // 2.0^53
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"string\": \"foobar\", \n"
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"empty-string\": \"\", \n"
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"dictionary\": { \n"
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "    \"foo\": \"bar\",\n"
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "    \"hot\": \"dog\",\n"
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  }, \n"
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"empty-dictionary\": {}, \n"
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"list\": [ \"monkey\", \"balls\" ], \n"
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"empty-list\": [], \n"
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}");
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> v8_object =
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.ToV8Value(original_root.get(), context).As<v8::Object>();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(v8_object.IsEmpty());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(static_cast<const base::DictionaryValue&>(*original_root).size(),
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            v8_object->GetPropertyNames()->Length());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("null"))->IsNull());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("true"))->IsTrue());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("false"))->IsFalse());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("positive-int"))->IsInt32());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("negative-int"))->IsInt32());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("zero"))->IsInt32());
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("double"))->IsNumber());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v8_object->Get(v8::String::New("big-integral-double"))->IsNumber());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("string"))->IsString());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("empty-string"))->IsString());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("dictionary"))->IsObject());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("empty-dictionary"))->IsObject());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("list"))->IsArray());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(v8_object->Get(v8::String::New("empty-list"))->IsArray());
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> new_root(converter.FromV8Value(v8_object, context));
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_NE(original_root.get(), new_root.get());
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(original_root->Equals(new_root.get()));
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, KeysWithDots) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> original =
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("{ \"foo.bar\": \"baz\" }");
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> copy(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      converter.FromV8Value(
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.ToV8Value(original.get(), context), context));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(original->Equals(copy.get()));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up objects to throw when reading or writing 'foo'.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source =
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Object.prototype.__defineSetter__('foo', "
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });"
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Object.prototype.__defineGetter__('foo', "
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });";
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script->Run();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object(v8::Object::New());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object->Set(v8::String::New("bar"), v8::String::New("bar"));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting from v8 value should replace the foo property with null.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> converted(
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(converted.get());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://code.google.com/p/v8/issues/detail?id=1342
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(2u, converted->size());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_TRUE(IsNull(converted.get(), "foo"));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, converted->size());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", GetString(converted.get(), "bar"));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting to v8 value should drop the foo property.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converted->SetString("foo", "foo");
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> copy =
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.ToV8Value(converted.get(), context).As<v8::Object>();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(copy.IsEmpty());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, copy->GetPropertyNames()->Length());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", GetString(copy, "bar"));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "var arr = [];"
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "arr.__defineSetter__(0, "
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });"
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "arr.__defineGetter__(0, "
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    function() { throw new Error('muah!'); });"
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "arr[1] = 'bar';"
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return arr;"
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array = script->Run().As<v8::Array>();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(array.IsEmpty());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting from v8 value should replace the first item with null.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> converted(static_cast<base::ListValue*>(
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(array, context)));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(converted.get());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://code.google.com/p/v8/issues/detail?id=1342
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, converted->GetSize());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsNull(converted.get(), 0));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converting to v8 value should drop the first item and leave a hole.
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  converted.reset(static_cast<base::ListValue*>(
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("[ \"foo\", \"bar\" ]").release()));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> copy =
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.ToV8Value(converted.get(), context).As<v8::Array>();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(copy.IsEmpty());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, copy->Length());
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", GetString(copy, 1));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, WeirdTypes) {
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::RegExp> regex(
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v8::RegExp::New(v8::String::New("."), v8::RegExp::kNone));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                v8::Undefined(),
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_NULL,  // Arbitrary type, result is NULL.
3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                scoped_ptr<base::Value>());
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                v8::Date::New(1000),
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_DICTIONARY,
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::DictionaryValue()));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                regex,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_DICTIONARY,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::DictionaryValue()));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converter.SetDateAllowed(true);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                v8::Date::New(1000),
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_DOUBLE,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::FundamentalValue(1.0)));
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converter.SetRegExpAllowed(true);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestWeirdType(converter,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                regex,
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                base::Value::TYPE_STRING,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                scoped_ptr<base::Value>(new base::StringValue("/./")));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, Prototype) {
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Object.prototype.foo = 'foo';"
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return {};"
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result(
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.get());
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, result->size());
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return { foo: undefined, bar: null };"
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  converter.SetStripNullFromObjects(true);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result(
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.get());
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, result->size());
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = v8::Object::New().As<v8::Object>();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object->Set(v8::String::New("foo"), v8::String::New("bar"));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object->Set(v8::String::New("obj"), object);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> object_result(
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<base::DictionaryValue*>(
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          converter.FromV8Value(object, context)));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_result.get());
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, object_result->size());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsNull(object_result.get(), "obj"));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array = v8::Array::New().As<v8::Array>();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(array.IsEmpty());
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  array->Set(0, v8::String::New("1"));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  array->Set(1, array);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> list_result(
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(list_result.get());
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, list_result->GetSize());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsNull(list_result.get(), 1));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, WeirdProperties) {
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return {"
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "1: 'foo',"
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "'2': 'bar',"
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "true: 'baz',"
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "false: 'qux',"
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "null: 'quux',"
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "undefined: 'oops'"
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "};"
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(object.IsEmpty());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> actual(converter.FromV8Value(object, context));
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> expected = base::test::ParseJson(
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "{ \n"
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"1\": \"foo\", \n"
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"2\": \"bar\", \n"
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"true\": \"baz\", \n"
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"false\": \"qux\", \n"
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"null\": \"quux\", \n"
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  \"undefined\": \"oops\", \n"
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}");
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected->Equals(actual.get()));
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, ArrayGetters) {
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* source = "(function() {"
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "var a = [0];"
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "a.__defineGetter__(1, function() { return 'bar'; });"
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return a;"
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "})();";
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array = script->Run().As<v8::Array>();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(array.IsEmpty());
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> result(
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result.get());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2u, result->GetSize());
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Object> object;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* source = "(function() {"
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "return { foo: undefined, bar: null, baz: function(){} };"
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "})();";
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    object = script->Run().As<v8::Object>();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(object.IsEmpty());
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Handle<v8::Array> array;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* source = "(function() {"
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "return [ undefined, null, function(){} ];"
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "})();";
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array = script->Run().As<v8::Array>();
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(array.IsEmpty());
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ValueConverterImpl converter;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> actual_object(
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(object, context));
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::Value::Equals(
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("{ \"bar\": null }").get(), actual_object.get()));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Everything is null because JSON stringification preserves array length.
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<Value> actual_array(converter.FromV8Value(array, context));
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::Value::Equals(
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::test::ParseJson("[ null, null, null ]").get(), actual_array.get()));
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  V8ValueConverterImpl converter;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We check that the converter checks identity correctly by disabling the
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // optimization of using identity hashes.
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter);
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create the v8::Object to be converted.
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Handle<v8::Array> root(v8::Array::New(4));
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->Set(0, v8::Handle<v8::Object>(v8::Object::New()));
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->Set(1, v8::Handle<v8::Object>(v8::Object::New()));
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->Set(2, v8::Handle<v8::Object>(v8::Array::New(0)));
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->Set(3, v8::Handle<v8::Object>(v8::Array::New(0)));
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The expected base::Value result.
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]");
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(expected.get());
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The actual result.
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> value(converter.FromV8Value(root, context));
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(value.get());
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected->Equals(value.get()));
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(V8ValueConverterImplTest, DetectCycles) {
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  V8ValueConverterImpl converter;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a recursive array.
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Handle<v8::Array> recursive_array(v8::Array::New(1));
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recursive_array->Set(0, recursive_array);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first repetition should be trimmed and replaced by a null value.
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue expected_list;
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_list.Append(base::Value::CreateNullValue());
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The actual result.
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> actual_list(
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(recursive_array, context));
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(actual_list.get());
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected_list.Equals(actual_list.get()));
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Now create a recursive object
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string key("key");
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Handle<v8::Object> recursive_object(v8::Object::New());
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::TryCatch try_catch;
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recursive_object->Set(v8::String::New(key.c_str(), key.length()),
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        recursive_object);
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(try_catch.HasCaught());
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first repetition should be trimmed and replaced by a null value.
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue expected_dictionary;
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_dictionary.Set(key, base::Value::CreateNullValue());
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The actual result.
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> actual_dictionary(
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      converter.FromV8Value(recursive_object, context));
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(actual_dictionary.get());
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(expected_dictionary.Equals(actual_dictionary.get()));
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::HandleScope handle_scope(isolate_);
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Context::Scope context_scope(isolate_, context_);
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Context> context =
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      v8::Local<v8::Context>::New(isolate_, context_);
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc.
637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int kDepth = 1000;
638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char kKey[] = "key";
639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Object> deep_object = v8::Object::New();
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  v8::Local<v8::Object> leaf = deep_object;
643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 0; i < kDepth; ++i) {
644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    v8::Local<v8::Object> new_object = v8::Object::New();
645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    leaf->Set(v8::String::New(kKey), new_object);
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    leaf = new_object;
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  V8ValueConverterImpl converter;
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> value(converter.FromV8Value(deep_object, context));
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(value);
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Expected depth is kMaxRecursionDepth in v8_value_converter_impl.cc.
654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int kExpectedDepth = 100;
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::Value* current = value.get();
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int i = 1; i < kExpectedDepth; ++i) {
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::DictionaryValue* current_as_object = NULL;
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_TRUE(current->GetAsDictionary(&current_as_object)) << i;
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_TRUE(current_as_object->Get(kKey, &current)) << i;
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The leaf node shouldn't have any properties.
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::DictionaryValue empty;
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(Value::Equals(&empty, current)) << *current;
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
669