Chromium Code Reviews| Index: Source/bindings/v8/ScriptPromisePropertyTest.cpp |
| diff --git a/Source/bindings/v8/ScriptPromisePropertyTest.cpp b/Source/bindings/v8/ScriptPromisePropertyTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..415db47c63143da243eab7ca5c1435f2dc8c6bc7 |
| --- /dev/null |
| +++ b/Source/bindings/v8/ScriptPromisePropertyTest.cpp |
| @@ -0,0 +1,249 @@ |
| +// Copyright 2014 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 "config.h" |
| +#include "bindings/v8/ScriptPromiseProperty.h" |
| + |
| +#include "bindings/v8/DOMWrapperWorld.h" |
| +#include "bindings/v8/ScriptFunction.h" |
| +#include "bindings/v8/ScriptPromise.h" |
| +#include "bindings/v8/ScriptState.h" |
| +#include "bindings/v8/ScriptValue.h" |
| +#include "bindings/v8/V8Binding.h" |
| +#include "core/dom/Document.h" |
| +#include "core/events/Event.h" |
| +#include "core/testing/DummyPageHolder.h" |
| +#include "core/testing/GCObservation.h" |
| +#include "wtf/OwnPtr.h" |
| +#include "wtf/PassOwnPtr.h" |
| +#include "wtf/PassRefPtr.h" |
| +#include "wtf/RefPtr.h" |
| +#include <gtest/gtest.h> |
| +#include <v8.h> |
| + |
| +using namespace WebCore; |
| + |
| +namespace { |
| + |
| +class NotReached : public ScriptFunction { |
| +public: |
| + NotReached() : ScriptFunction(v8::Isolate::GetCurrent()) { } |
| + |
| +private: |
| + virtual ScriptValue call(ScriptValue) OVERRIDE; |
| +}; |
| + |
| +ScriptValue NotReached::call(ScriptValue) |
| +{ |
| + EXPECT_TRUE(false) << "'Unreachable' code was reached"; |
| + return ScriptValue(); |
| +} |
| + |
| +class StubFunction : public ScriptFunction { |
| +public: |
| + StubFunction(ScriptValue&, size_t& callCount); |
| + |
| +private: |
| + virtual ScriptValue call(ScriptValue) OVERRIDE; |
| + |
| + ScriptValue& m_value; |
| + size_t& m_callCount; |
| +}; |
| + |
| +StubFunction::StubFunction(ScriptValue& value, size_t& callCount) |
| + : ScriptFunction(v8::Isolate::GetCurrent()) |
| + , m_value(value) |
| + , m_callCount(callCount) |
| +{ |
| +} |
| + |
| +ScriptValue StubFunction::call(ScriptValue arg) |
| +{ |
| + m_value = arg; |
| + m_callCount++; |
| + return ScriptValue(); |
| +} |
| + |
| +class ScriptPromisePropertyTest : public ::testing::Test { |
| +protected: |
| + ScriptPromisePropertyTest() |
| + : m_page(DummyPageHolder::create(IntSize(1, 1))) |
| + { |
| + } |
| + |
| + virtual ~ScriptPromisePropertyTest() |
| + { |
| + m_page.clear(); |
| + gc(); |
| + } |
| + |
| + Document& document() { return m_page->document(); } |
| + v8::Isolate* isolate() { return toIsolate(&document()); } |
| + ScriptState* scriptState() { return ScriptState::forMainWorld(document().frame()); } |
| + void gc() { v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection); } |
| + |
| + PassOwnPtr<ScriptFunction> notReached() { return adoptPtr(new NotReached()); } |
| + PassOwnPtr<ScriptFunction> stub(ScriptValue& value, size_t& callCount) { return adoptPtr(new StubFunction(value, callCount)); } |
| + |
| + // These tests use Event because it is simple to manufacture lots of events. |
| + |
| + ScriptValue wrap(PassRefPtrWillBeRawPtr<Event> event) |
| + { |
| + ScriptState::Scope scope(scriptState()); |
| + return ScriptValue(scriptState(), V8ValueTraits<Event>::toV8Value(event, scriptState()->context()->Global(), isolate())); |
| + } |
| + |
| + typedef ScriptPromiseProperty<RefPtrWillBeMember<Event>, Event*, Event*> Property; |
| + PassRefPtrWillBeRawPtr<Property> newProperty() { return Property::create(&document(), Event::create(), "test"); } |
| + |
| +private: |
| + OwnPtr<DummyPageHolder> m_page; |
| +}; |
| + |
| +TEST_F(ScriptPromisePropertyTest, Promise_IsStableObject) |
| +{ |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + ScriptPromise v = p->promise(DOMWrapperWorld::mainWorld()); |
| + ScriptPromise w = p->promise(DOMWrapperWorld::mainWorld()); |
| + EXPECT_EQ(v, w); |
|
yhirano
2014/07/01 04:38:14
EXPECT_FALSE(v.isEmpty())
yhirano
2014/07/01 04:38:14
State check?
|
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Promise_IsStableObjectAfterSettling) |
| +{ |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + ScriptPromise v = p->promise(DOMWrapperWorld::mainWorld()); |
| + |
| + RefPtrWillBeRawPtr<Event> value(Event::create()); |
| + p->resolve(value.get()); |
| + |
| + ScriptPromise w = p->promise(DOMWrapperWorld::mainWorld()); |
| + EXPECT_EQ(v, w); |
|
yhirano
2014/07/01 04:38:14
State check?
yhirano
2014/07/01 04:38:14
EXPECT_FALSE(v.isEmpty())
|
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Promise_DoesNotImpedeGarbageCollection) |
| +{ |
| + RefPtrWillBeRawPtr<Event> holder(Event::create()); |
| + ScriptValue holderWrapper = wrap(holder); |
| + |
| + RefPtrWillBeRawPtr<Property> p(Property::create(&document(), holder, "test")); |
| + |
| + RefPtrWillBeRawPtr<GCObservation> observation; |
| + { |
| + ScriptState::Scope scope(scriptState()); |
| + observation = GCObservation::create(p->promise(DOMWrapperWorld::mainWorld()).v8Value()); |
| + } |
| + |
| + gc(); |
| + EXPECT_FALSE(observation->wasCollected()); |
| + |
| + holderWrapper.clear(); |
| + gc(); |
| + EXPECT_TRUE(observation->wasCollected()); |
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Resolve_ResolvesScriptPromise) |
| +{ |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + |
| + ScriptPromise promise = p->promise(DOMWrapperWorld::mainWorld()); |
| + ScriptValue value; |
| + size_t nResolveCalls = 0; |
| + |
| + { |
| + ScriptState::Scope scope(scriptState()); |
| + promise.then(stub(value, nResolveCalls), notReached()); |
| + } |
| + |
| + RefPtrWillBeRawPtr<Event> event(Event::create()); |
| + p->resolve(event.get()); |
| + isolate()->RunMicrotasks(); |
| + |
| + EXPECT_EQ(1u, nResolveCalls); |
| + EXPECT_EQ(wrap(event), value); |
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Resolve_ChangesState) |
| +{ |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + EXPECT_EQ(Property::Pending, p->state()); |
| + RefPtrWillBeRawPtr<Event> value(Event::create()); |
| + p->resolve(value.get()); |
| + EXPECT_EQ(Property::Resolved, p->state()); |
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Reject_RejectsScriptPromise) |
| +{ |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + |
| + RefPtrWillBeRawPtr<Event> event(Event::create()); |
| + p->reject(event.get()); |
| + |
| + ScriptValue value; |
| + size_t nRejectCalls = 0; |
| + |
| + { |
| + ScriptState::Scope scope(scriptState()); |
| + p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), stub(value, nRejectCalls)); |
| + } |
| + |
| + isolate()->RunMicrotasks(); |
| + |
| + EXPECT_EQ(1u, nRejectCalls); |
| + EXPECT_EQ(wrap(event), value); |
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Settle_IsIdempotent) |
| +{ |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + |
| + RefPtrWillBeRawPtr<Event> eventA(Event::create()); |
| + p->reject(eventA.get()); |
| + RefPtrWillBeRawPtr<Event> eventB(Event::create()); |
| + p->resolve(eventB.get()); |
| + |
| + ScriptValue value; |
| + size_t nRejectCalls = 0; |
| + |
| + { |
| + ScriptState::Scope scope(scriptState()); |
| + p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), stub(value, nRejectCalls)); |
| + } |
| + |
| + isolate()->RunMicrotasks(); |
| + |
| + EXPECT_EQ(1u, nRejectCalls); |
| + EXPECT_EQ(wrap(eventA), value); |
| + |
| + RefPtrWillBeRawPtr<Event> eventC(Event::create()); |
| + p->reject(eventC.get()); |
| + EXPECT_EQ(1u, nRejectCalls); |
| +} |
| + |
| +TEST_F(ScriptPromisePropertyTest, Settle_WaitsForResume) |
| +{ |
| + document().suspendScheduledTasks(); |
| + |
| + RefPtrWillBeRawPtr<Property> p(newProperty()); |
| + |
| + RefPtrWillBeRawPtr<Event> event(Event::create()); |
| + p->resolve(event.get()); |
| + |
| + ScriptValue value; |
| + size_t nResolveCalls = 0; |
| + |
| + { |
| + ScriptState::Scope scope(scriptState()); |
| + p->promise(DOMWrapperWorld::mainWorld()).then(stub(value, nResolveCalls), notReached()); |
| + } |
| + |
| + isolate()->RunMicrotasks(); |
| + EXPECT_EQ(0u, nResolveCalls); |
| + |
| + document().resumeScheduledTasks(); |
| + isolate()->RunMicrotasks(); |
| + EXPECT_EQ(1u, nResolveCalls); |
| + EXPECT_EQ(wrap(event), value); |
| +} |
| + |
| +} // namespace |