1/* 2 * Copyright (C) 2014 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "bindings/core/v8/ScriptPromise.h" 33 34#include "bindings/core/v8/ScriptFunction.h" 35#include "bindings/core/v8/ScriptValue.h" 36#include "bindings/core/v8/V8Binding.h" 37#include "core/dom/DOMException.h" 38#include "core/dom/ExceptionCode.h" 39 40#include <gtest/gtest.h> 41#include <v8.h> 42 43namespace blink { 44 45namespace { 46 47void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { } 48 49class Function : public ScriptFunction { 50public: 51 static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, String* value) 52 { 53 Function* self = new Function(scriptState, value); 54 return self->bindToV8Function(); 55 } 56 57private: 58 Function(ScriptState* scriptState, String* value) 59 : ScriptFunction(scriptState) 60 , m_value(value) 61 { 62 } 63 64 virtual ScriptValue call(ScriptValue value) OVERRIDE 65 { 66 ASSERT(!value.isEmpty()); 67 *m_value = toCoreString(value.v8Value()->ToString()); 68 return value; 69 } 70 71 String* m_value; 72}; 73 74class ScriptPromiseTest : public testing::Test { 75public: 76 ScriptPromiseTest() 77 : m_scope(v8::Isolate::GetCurrent()) 78 { 79 } 80 81 ~ScriptPromiseTest() 82 { 83 // FIXME: We put this statement here to clear an exception from the isolate. 84 createClosure(callback, v8::Undefined(m_scope.isolate()), m_scope.isolate()); 85 86 // Execute all pending microtasks 87 isolate()->RunMicrotasks(); 88 } 89 90 ScriptState* scriptState() const { return m_scope.scriptState(); } 91 v8::Isolate* isolate() const { return m_scope.isolate(); } 92 93protected: 94 typedef ScriptPromise::InternalResolver Resolver; 95 V8TestingScope m_scope; 96}; 97 98TEST_F(ScriptPromiseTest, constructFromNonPromise) 99{ 100 v8::TryCatch trycatch; 101 ScriptPromise promise(scriptState(), v8::Undefined(isolate())); 102 ASSERT_TRUE(trycatch.HasCaught()); 103 ASSERT_TRUE(promise.isEmpty()); 104} 105 106TEST_F(ScriptPromiseTest, thenResolve) 107{ 108 Resolver resolver(scriptState()); 109 ScriptPromise promise = resolver.promise(); 110 String onFulfilled, onRejected; 111 promise.then(Function::createFunction(scriptState(), &onFulfilled), Function::createFunction(scriptState(), &onRejected)); 112 113 ASSERT_FALSE(promise.isEmpty()); 114 EXPECT_EQ(String(), onFulfilled); 115 EXPECT_EQ(String(), onRejected); 116 117 isolate()->RunMicrotasks(); 118 resolver.resolve(v8String(isolate(), "hello")); 119 120 EXPECT_EQ(String(), onFulfilled); 121 EXPECT_EQ(String(), onRejected); 122 123 isolate()->RunMicrotasks(); 124 125 EXPECT_EQ("hello", onFulfilled); 126 EXPECT_EQ(String(), onRejected); 127} 128 129TEST_F(ScriptPromiseTest, resolveThen) 130{ 131 Resolver resolver(scriptState()); 132 ScriptPromise promise = resolver.promise(); 133 String onFulfilled, onRejected; 134 resolver.resolve(v8String(isolate(), "hello")); 135 promise.then(Function::createFunction(scriptState(), &onFulfilled), Function::createFunction(scriptState(), &onRejected)); 136 137 ASSERT_FALSE(promise.isEmpty()); 138 EXPECT_EQ(String(), onFulfilled); 139 EXPECT_EQ(String(), onRejected); 140 141 isolate()->RunMicrotasks(); 142 143 EXPECT_EQ("hello", onFulfilled); 144 EXPECT_EQ(String(), onRejected); 145} 146 147TEST_F(ScriptPromiseTest, thenReject) 148{ 149 Resolver resolver(scriptState()); 150 ScriptPromise promise = resolver.promise(); 151 String onFulfilled, onRejected; 152 promise.then(Function::createFunction(scriptState(), &onFulfilled), Function::createFunction(scriptState(), &onRejected)); 153 154 ASSERT_FALSE(promise.isEmpty()); 155 EXPECT_EQ(String(), onFulfilled); 156 EXPECT_EQ(String(), onRejected); 157 158 isolate()->RunMicrotasks(); 159 resolver.reject(v8String(isolate(), "hello")); 160 161 EXPECT_EQ(String(), onFulfilled); 162 EXPECT_EQ(String(), onRejected); 163 164 isolate()->RunMicrotasks(); 165 166 EXPECT_EQ(String(), onFulfilled); 167 EXPECT_EQ("hello", onRejected); 168} 169 170TEST_F(ScriptPromiseTest, rejectThen) 171{ 172 Resolver resolver(scriptState()); 173 ScriptPromise promise = resolver.promise(); 174 String onFulfilled, onRejected; 175 resolver.reject(v8String(isolate(), "hello")); 176 promise.then(Function::createFunction(scriptState(), &onFulfilled), Function::createFunction(scriptState(), &onRejected)); 177 178 ASSERT_FALSE(promise.isEmpty()); 179 EXPECT_EQ(String(), onFulfilled); 180 EXPECT_EQ(String(), onRejected); 181 182 isolate()->RunMicrotasks(); 183 184 EXPECT_EQ(String(), onFulfilled); 185 EXPECT_EQ("hello", onRejected); 186} 187 188TEST_F(ScriptPromiseTest, castPromise) 189{ 190 ScriptPromise promise = Resolver(scriptState()).promise(); 191 ScriptPromise newPromise = ScriptPromise::cast(scriptState(), promise.v8Value()); 192 193 ASSERT_FALSE(promise.isEmpty()); 194 EXPECT_EQ(promise.v8Value(), newPromise.v8Value()); 195} 196 197TEST_F(ScriptPromiseTest, castNonPromise) 198{ 199 String onFulfilled1, onFulfilled2, onRejected1, onRejected2; 200 201 ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); 202 ScriptPromise promise1 = ScriptPromise::cast(scriptState(), ScriptValue(value)); 203 ScriptPromise promise2 = ScriptPromise::cast(scriptState(), ScriptValue(value)); 204 promise1.then(Function::createFunction(scriptState(), &onFulfilled1), Function::createFunction(scriptState(), &onRejected1)); 205 promise2.then(Function::createFunction(scriptState(), &onFulfilled2), Function::createFunction(scriptState(), &onRejected2)); 206 207 ASSERT_FALSE(promise1.isEmpty()); 208 ASSERT_FALSE(promise2.isEmpty()); 209 EXPECT_NE(promise1.v8Value(), promise2.v8Value()); 210 211 ASSERT_TRUE(promise1.v8Value()->IsPromise()); 212 ASSERT_TRUE(promise2.v8Value()->IsPromise()); 213 214 EXPECT_EQ(String(), onFulfilled1); 215 EXPECT_EQ(String(), onFulfilled2); 216 EXPECT_EQ(String(), onRejected1); 217 EXPECT_EQ(String(), onRejected2); 218 219 isolate()->RunMicrotasks(); 220 221 EXPECT_EQ("hello", onFulfilled1); 222 EXPECT_EQ("hello", onFulfilled2); 223 EXPECT_EQ(String(), onRejected1); 224 EXPECT_EQ(String(), onRejected2); 225} 226 227TEST_F(ScriptPromiseTest, reject) 228{ 229 String onFulfilled, onRejected; 230 231 ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); 232 ScriptPromise promise = ScriptPromise::reject(scriptState(), ScriptValue(value)); 233 promise.then(Function::createFunction(scriptState(), &onFulfilled), Function::createFunction(scriptState(), &onRejected)); 234 235 ASSERT_FALSE(promise.isEmpty()); 236 ASSERT_TRUE(promise.v8Value()->IsPromise()); 237 238 EXPECT_EQ(String(), onFulfilled); 239 EXPECT_EQ(String(), onRejected); 240 241 isolate()->RunMicrotasks(); 242 243 EXPECT_EQ(String(), onFulfilled); 244 EXPECT_EQ("hello", onRejected); 245} 246 247TEST_F(ScriptPromiseTest, rejectWithExceptionState) 248{ 249 String onFulfilled, onRejected; 250 ScriptPromise promise = ScriptPromise::rejectWithDOMException(scriptState(), DOMException::create(SyntaxError, "some syntax error")); 251 promise.then(Function::createFunction(scriptState(), &onFulfilled), Function::createFunction(scriptState(), &onRejected)); 252 253 ASSERT_FALSE(promise.isEmpty()); 254 EXPECT_EQ(String(), onFulfilled); 255 EXPECT_EQ(String(), onRejected); 256 257 isolate()->RunMicrotasks(); 258 259 EXPECT_EQ(String(), onFulfilled); 260 EXPECT_EQ("SyntaxError: some syntax error", onRejected); 261} 262 263} // namespace 264 265} // namespace blink 266