OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/stl_util.h" | |
8 #include "base/test/values_test_util.h" | 9 #include "base/test/values_test_util.h" |
9 #include "base/values.h" | 10 #include "base/values.h" |
10 #include "content/renderer/v8_value_converter_impl.h" | 11 #include "content/renderer/v8_value_converter_impl.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "v8/include/v8.h" | 13 #include "v8/include/v8.h" |
13 | 14 |
14 namespace content { | 15 namespace content { |
15 | 16 |
17 // To improve the performance of | |
18 // V8ValueConverterImpl::UpdateAndCheckUniqueness, identity hashes of objects | |
19 // are used during checking for duplicates. For testing purposes we need to | |
20 // ignore the hash sometimes. Create this helper object to avoid using identity | |
21 // hashes for the lifetime of the helper. | |
22 class ScopedAvoidIdentityHashForTesting { | |
vabr (Chromium)
2013/03/15 14:37:45
This class cannot be in the anonymous namespace, b
| |
23 public: | |
24 // The hashes will be ignored in |converter|, which must not be NULL and it | |
25 // must outlive the created instance of this helper. | |
26 explicit ScopedAvoidIdentityHashForTesting( | |
27 content::V8ValueConverterImpl* converter); | |
28 ~ScopedAvoidIdentityHashForTesting(); | |
29 | |
30 private: | |
31 content::V8ValueConverterImpl* converter_; | |
32 | |
33 DISALLOW_COPY_AND_ASSIGN(ScopedAvoidIdentityHashForTesting); | |
34 }; | |
35 | |
36 ScopedAvoidIdentityHashForTesting::ScopedAvoidIdentityHashForTesting( | |
37 content::V8ValueConverterImpl* converter) | |
38 : converter_(converter) { | |
39 CHECK(converter_); | |
40 converter_->avoid_identity_hash_for_testing_ = true; | |
41 } | |
42 | |
43 ScopedAvoidIdentityHashForTesting::~ScopedAvoidIdentityHashForTesting() { | |
44 converter_->avoid_identity_hash_for_testing_ = false; | |
45 } | |
46 | |
16 namespace { | 47 namespace { |
17 | 48 |
18 // A dumb getter for an object's named callback. | 49 // A dumb getter for an object's named callback. |
19 v8::Handle<v8::Value> NamedCallbackGetter(v8::Local<v8::String> name, | 50 v8::Handle<v8::Value> NamedCallbackGetter(v8::Local<v8::String> name, |
20 const v8::AccessorInfo& info) { | 51 const v8::AccessorInfo& info) { |
21 return v8::String::New("bar"); | 52 return v8::String::New("bar"); |
22 } | 53 } |
23 | 54 |
24 } // namespace | 55 } // namespace |
25 | 56 |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
542 converter.FromV8Value(object, context_)); | 573 converter.FromV8Value(object, context_)); |
543 EXPECT_TRUE(base::Value::Equals( | 574 EXPECT_TRUE(base::Value::Equals( |
544 base::test::ParseJson("{ \"bar\": null }").get(), actual_object.get())); | 575 base::test::ParseJson("{ \"bar\": null }").get(), actual_object.get())); |
545 | 576 |
546 // Everything is null because JSON stringification preserves array length. | 577 // Everything is null because JSON stringification preserves array length. |
547 scoped_ptr<Value> actual_array(converter.FromV8Value(array, context_)); | 578 scoped_ptr<Value> actual_array(converter.FromV8Value(array, context_)); |
548 EXPECT_TRUE(base::Value::Equals( | 579 EXPECT_TRUE(base::Value::Equals( |
549 base::test::ParseJson("[ null, null, null ]").get(), actual_array.get())); | 580 base::test::ParseJson("[ null, null, null ]").get(), actual_array.get())); |
550 } | 581 } |
551 | 582 |
583 TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) { | |
584 v8::Context::Scope context_scope(context_); | |
585 v8::HandleScope handle_scope; | |
586 V8ValueConverterImpl converter; | |
587 | |
588 // We check that the converter checks identity correctly by disabling the | |
589 // optimization of using identity hashes. | |
590 ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter); | |
591 | |
592 // Create the v8::Object to be converted. | |
593 v8::Handle<v8::Array> root(v8::Array::New(4)); | |
594 root->Set(0, v8::Handle<v8::Object>(v8::Object::New())); | |
595 root->Set(1, v8::Handle<v8::Object>(v8::Object::New())); | |
596 root->Set(2, v8::Handle<v8::Object>(v8::Array::New(0))); | |
597 root->Set(3, v8::Handle<v8::Object>(v8::Array::New(0))); | |
598 | |
599 // The expected base::Value result. | |
600 scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]"); | |
601 ASSERT_TRUE(expected.get()); | |
602 | |
603 // The actual result. | |
604 scoped_ptr<base::Value> value(converter.FromV8Value(root, context_)); | |
605 ASSERT_TRUE(value.get()); | |
606 | |
607 EXPECT_TRUE(expected->Equals(value.get())); | |
608 } | |
609 | |
610 TEST_F(V8ValueConverterImplTest, DetectCycles) { | |
vabr (Chromium)
2013/03/15 14:37:45
If this test does not succeed, it will most likely
| |
611 v8::Context::Scope context_scope(context_); | |
612 v8::HandleScope handle_scope; | |
613 V8ValueConverterImpl converter; | |
614 | |
615 // Create a recursive array. | |
616 v8::Handle<v8::Array> recursive_array(v8::Array::New(1)); | |
617 recursive_array->Set(0, recursive_array); | |
618 | |
619 // The first repetition should be trimmed and replaced by a null value. | |
620 base::ListValue expected_list; | |
621 expected_list.Append(base::Value::CreateNullValue()); | |
622 | |
623 // The actual result. | |
624 scoped_ptr<base::Value> actual_list( | |
625 converter.FromV8Value(recursive_array, context_)); | |
626 ASSERT_TRUE(actual_list.get()); | |
627 | |
628 EXPECT_TRUE(expected_list.Equals(actual_list.get())); | |
629 | |
630 // Now create a recursive object | |
631 const std::string key("key"); | |
632 v8::Handle<v8::Object> recursive_object(v8::Object::New()); | |
633 v8::TryCatch try_catch; | |
634 recursive_object->Set(v8::String::New(key.c_str(), key.length()), | |
635 recursive_object); | |
636 ASSERT_FALSE(try_catch.HasCaught()); | |
637 | |
638 // The first repetition should be trimmed and replaced by a null value. | |
639 base::DictionaryValue expected_dictionary; | |
640 expected_dictionary.Set(key, base::Value::CreateNullValue()); | |
641 | |
642 // The actual result. | |
643 scoped_ptr<base::Value> actual_dictionary( | |
644 converter.FromV8Value(recursive_object, context_)); | |
645 ASSERT_TRUE(actual_dictionary.get()); | |
646 | |
647 EXPECT_TRUE(expected_dictionary.Equals(actual_dictionary.get())); | |
648 } | |
649 | |
552 } // namespace content | 650 } // namespace content |
OLD | NEW |