1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "config.h" 6#include "core/streams/ReadableStream.h" 7 8#include "bindings/core/v8/ExceptionState.h" 9#include "bindings/core/v8/ScriptPromiseResolver.h" 10#include "bindings/core/v8/ScriptState.h" 11#include "bindings/core/v8/V8Binding.h" 12#include "core/dom/DOMException.h" 13#include "core/dom/Document.h" 14#include "core/dom/ExceptionCode.h" 15#include "core/streams/ReadableStreamImpl.h" 16#include "core/streams/UnderlyingSource.h" 17#include "core/testing/DummyPageHolder.h" 18#include <gmock/gmock.h> 19#include <gtest/gtest.h> 20 21namespace blink { 22 23using ::testing::_; 24using ::testing::InSequence; 25using ::testing::Invoke; 26using ::testing::Return; 27 28namespace { 29 30typedef ::testing::StrictMock<::testing::MockFunction<void(int)> > Checkpoint; 31typedef ReadableStreamImpl<ReadableStreamChunkTypeTraits<String> > StringStream; 32 33class StringCapturingFunction : public ScriptFunction { 34public: 35 static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, String* value) 36 { 37 StringCapturingFunction* self = new StringCapturingFunction(scriptState, value); 38 return self->bindToV8Function(); 39 } 40 41private: 42 StringCapturingFunction(ScriptState* scriptState, String* value) 43 : ScriptFunction(scriptState) 44 , m_value(value) 45 { 46 } 47 48 virtual ScriptValue call(ScriptValue value) OVERRIDE 49 { 50 ASSERT(!value.isEmpty()); 51 *m_value = toCoreString(value.v8Value()->ToString()); 52 return value; 53 } 54 55 String* m_value; 56}; 57 58class MockUnderlyingSource : public GarbageCollectedFinalized<MockUnderlyingSource>, public UnderlyingSource { 59 USING_GARBAGE_COLLECTED_MIXIN(MockUnderlyingSource); 60public: 61 virtual ~MockUnderlyingSource() { } 62 63 MOCK_METHOD0(pullSource, void()); 64 MOCK_METHOD2(cancelSource, ScriptPromise(ScriptState*, ScriptValue)); 65}; 66 67class ThrowError { 68public: 69 explicit ThrowError(const String& message) 70 : m_message(message) { } 71 72 void operator()(ExceptionState* exceptionState) 73 { 74 exceptionState->throwTypeError(m_message); 75 } 76 77private: 78 String m_message; 79}; 80 81} // unnamed namespace 82 83class ReadableStreamTest : public ::testing::Test { 84public: 85 ReadableStreamTest() 86 : m_page(DummyPageHolder::create(IntSize(1, 1))) 87 , m_scope(scriptState()) 88 , m_underlyingSource(new ::testing::StrictMock<MockUnderlyingSource>) 89 , m_exceptionState(ExceptionState::ConstructionContext, "property", "interface", scriptState()->context()->Global(), isolate()) 90 { 91 } 92 93 virtual ~ReadableStreamTest() 94 { 95 } 96 97 ScriptState* scriptState() { return ScriptState::forMainWorld(m_page->document().frame()); } 98 v8::Isolate* isolate() { return scriptState()->isolate(); } 99 100 v8::Handle<v8::Function> createCaptor(String* value) 101 { 102 return StringCapturingFunction::createFunction(scriptState(), value); 103 } 104 105 StringStream* construct() 106 { 107 StringStream* stream = new StringStream(scriptState()->executionContext(), m_underlyingSource); 108 stream->didSourceStart(); 109 return stream; 110 } 111 112 OwnPtr<DummyPageHolder> m_page; 113 ScriptState::Scope m_scope; 114 Persistent<MockUnderlyingSource> m_underlyingSource; 115 ExceptionState m_exceptionState; 116}; 117 118TEST_F(ReadableStreamTest, Start) 119{ 120 StringStream* stream = new StringStream(scriptState()->executionContext(), m_underlyingSource); 121 EXPECT_FALSE(m_exceptionState.hadException()); 122 EXPECT_FALSE(stream->isStarted()); 123 EXPECT_FALSE(stream->isDraining()); 124 EXPECT_FALSE(stream->isPulling()); 125 EXPECT_EQ(stream->state(), ReadableStream::Waiting); 126 127 stream->didSourceStart(); 128 129 EXPECT_TRUE(stream->isStarted()); 130 EXPECT_FALSE(stream->isDraining()); 131 EXPECT_FALSE(stream->isPulling()); 132 EXPECT_EQ(stream->state(), ReadableStream::Waiting); 133} 134 135TEST_F(ReadableStreamTest, StartFail) 136{ 137 StringStream* stream = new StringStream(scriptState()->executionContext(), m_underlyingSource); 138 EXPECT_FALSE(m_exceptionState.hadException()); 139 EXPECT_FALSE(stream->isStarted()); 140 EXPECT_FALSE(stream->isDraining()); 141 EXPECT_FALSE(stream->isPulling()); 142 EXPECT_EQ(stream->state(), ReadableStream::Waiting); 143 144 stream->error(DOMException::create(NotFoundError)); 145 146 EXPECT_FALSE(stream->isStarted()); 147 EXPECT_FALSE(stream->isDraining()); 148 EXPECT_FALSE(stream->isPulling()); 149 EXPECT_EQ(stream->state(), ReadableStream::Errored); 150} 151 152TEST_F(ReadableStreamTest, WaitOnWaiting) 153{ 154 StringStream* stream = construct(); 155 Checkpoint checkpoint; 156 157 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 158 EXPECT_TRUE(stream->isStarted()); 159 EXPECT_FALSE(stream->isPulling()); 160 161 { 162 InSequence s; 163 EXPECT_CALL(checkpoint, Call(0)); 164 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 165 EXPECT_CALL(checkpoint, Call(1)); 166 } 167 168 checkpoint.Call(0); 169 ScriptPromise p = stream->wait(scriptState()); 170 ScriptPromise q = stream->wait(scriptState()); 171 checkpoint.Call(1); 172 173 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 174 EXPECT_TRUE(stream->isPulling()); 175 EXPECT_EQ(q, p); 176} 177 178TEST_F(ReadableStreamTest, WaitDuringStarting) 179{ 180 StringStream* stream = new StringStream(scriptState()->executionContext(), m_underlyingSource); 181 Checkpoint checkpoint; 182 183 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 184 EXPECT_FALSE(stream->isStarted()); 185 EXPECT_FALSE(stream->isPulling()); 186 187 { 188 InSequence s; 189 EXPECT_CALL(checkpoint, Call(0)); 190 EXPECT_CALL(checkpoint, Call(1)); 191 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 192 } 193 194 checkpoint.Call(0); 195 stream->wait(scriptState()); 196 checkpoint.Call(1); 197 198 EXPECT_TRUE(stream->isPulling()); 199 200 stream->didSourceStart(); 201 202 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 203 EXPECT_TRUE(stream->isPulling()); 204} 205 206TEST_F(ReadableStreamTest, WaitAndError) 207{ 208 StringStream* stream = construct(); 209 String onFulfilled, onRejected; 210 211 { 212 InSequence s; 213 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 214 } 215 216 ScriptPromise promise = stream->wait(scriptState()); 217 promise.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 218 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 219 EXPECT_TRUE(stream->isPulling()); 220 stream->error(DOMException::create(NotFoundError, "hello, error")); 221 EXPECT_EQ(ReadableStream::Errored, stream->state()); 222 EXPECT_TRUE(stream->isPulling()); 223 EXPECT_TRUE(onFulfilled.isNull()); 224 EXPECT_TRUE(onRejected.isNull()); 225 226 isolate()->RunMicrotasks(); 227 EXPECT_TRUE(onFulfilled.isNull()); 228 EXPECT_EQ(promise, stream->wait(scriptState())); 229 EXPECT_EQ("NotFoundError: hello, error", onRejected); 230} 231 232TEST_F(ReadableStreamTest, ErrorAndEnqueue) 233{ 234 StringStream* stream = construct(); 235 236 stream->error(DOMException::create(NotFoundError, "error")); 237 EXPECT_EQ(ReadableStream::Errored, stream->state()); 238 239 bool result = stream->enqueue("hello"); 240 EXPECT_FALSE(result); 241 EXPECT_EQ(ReadableStream::Errored, stream->state()); 242} 243 244TEST_F(ReadableStreamTest, CloseAndEnqueue) 245{ 246 StringStream* stream = construct(); 247 248 stream->close(); 249 EXPECT_EQ(ReadableStream::Closed, stream->state()); 250 251 bool result = stream->enqueue("hello"); 252 EXPECT_FALSE(result); 253 EXPECT_EQ(ReadableStream::Closed, stream->state()); 254} 255 256TEST_F(ReadableStreamTest, EnqueueAndWait) 257{ 258 StringStream* stream = construct(); 259 String onFulfilled, onRejected; 260 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 261 262 bool result = stream->enqueue("hello"); 263 EXPECT_TRUE(result); 264 EXPECT_EQ(ReadableStream::Readable, stream->state()); 265 266 stream->wait(scriptState()).then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 267 EXPECT_EQ(ReadableStream::Readable, stream->state()); 268 EXPECT_FALSE(stream->isPulling()); 269 EXPECT_TRUE(onFulfilled.isNull()); 270 EXPECT_TRUE(onRejected.isNull()); 271 272 isolate()->RunMicrotasks(); 273 EXPECT_EQ(ReadableStream::Readable, stream->state()); 274 EXPECT_FALSE(stream->isPulling()); 275 EXPECT_EQ("undefined", onFulfilled); 276 EXPECT_TRUE(onRejected.isNull()); 277} 278 279TEST_F(ReadableStreamTest, WaitAndEnqueue) 280{ 281 StringStream* stream = construct(); 282 String onFulfilled, onRejected; 283 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 284 285 { 286 InSequence s; 287 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 288 } 289 290 stream->wait(scriptState()).then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 291 isolate()->RunMicrotasks(); 292 293 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 294 EXPECT_TRUE(stream->isPulling()); 295 EXPECT_TRUE(onFulfilled.isNull()); 296 EXPECT_TRUE(onRejected.isNull()); 297 298 bool result = stream->enqueue("hello"); 299 EXPECT_TRUE(result); 300 EXPECT_EQ(ReadableStream::Readable, stream->state()); 301 EXPECT_FALSE(stream->isPulling()); 302 EXPECT_TRUE(onFulfilled.isNull()); 303 EXPECT_TRUE(onRejected.isNull()); 304 305 isolate()->RunMicrotasks(); 306 EXPECT_EQ("undefined", onFulfilled); 307 EXPECT_TRUE(onRejected.isNull()); 308} 309 310TEST_F(ReadableStreamTest, WaitAndEnqueueAndError) 311{ 312 StringStream* stream = construct(); 313 String onFulfilled, onRejected; 314 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 315 316 { 317 InSequence s; 318 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 319 } 320 321 ScriptPromise promise = stream->wait(scriptState()); 322 promise.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 323 isolate()->RunMicrotasks(); 324 325 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 326 EXPECT_TRUE(stream->isPulling()); 327 EXPECT_TRUE(onFulfilled.isNull()); 328 EXPECT_TRUE(onRejected.isNull()); 329 330 bool result = stream->enqueue("hello"); 331 EXPECT_TRUE(result); 332 EXPECT_EQ(ReadableStream::Readable, stream->state()); 333 EXPECT_FALSE(stream->isPulling()); 334 EXPECT_TRUE(onFulfilled.isNull()); 335 EXPECT_TRUE(onRejected.isNull()); 336 337 isolate()->RunMicrotasks(); 338 EXPECT_EQ("undefined", onFulfilled); 339 EXPECT_TRUE(onRejected.isNull()); 340 341 stream->error(DOMException::create(NotFoundError, "error")); 342 EXPECT_EQ(ReadableStream::Errored, stream->state()); 343 344 EXPECT_NE(promise, stream->wait(scriptState())); 345} 346 347TEST_F(ReadableStreamTest, CloseWhenWaiting) 348{ 349 String onWaitFulfilled, onWaitRejected; 350 String onClosedFulfilled, onClosedRejected; 351 352 StringStream* stream = construct(); 353 354 { 355 InSequence s; 356 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 357 } 358 359 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 360 stream->wait(scriptState()).then(createCaptor(&onWaitFulfilled), createCaptor(&onWaitRejected)); 361 stream->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createCaptor(&onClosedRejected)); 362 363 isolate()->RunMicrotasks(); 364 EXPECT_TRUE(onWaitFulfilled.isNull()); 365 EXPECT_TRUE(onWaitRejected.isNull()); 366 EXPECT_TRUE(onClosedFulfilled.isNull()); 367 EXPECT_TRUE(onClosedRejected.isNull()); 368 369 stream->close(); 370 EXPECT_EQ(ReadableStream::Closed, stream->state()); 371 isolate()->RunMicrotasks(); 372 EXPECT_EQ("undefined", onWaitFulfilled); 373 EXPECT_TRUE(onWaitRejected.isNull()); 374 EXPECT_EQ("undefined", onClosedFulfilled); 375 EXPECT_TRUE(onClosedRejected.isNull()); 376} 377 378TEST_F(ReadableStreamTest, CloseWhenErrored) 379{ 380 String onFulfilled, onRejected; 381 StringStream* stream = construct(); 382 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 383 stream->closed(scriptState()).then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 384 385 stream->error(DOMException::create(NotFoundError, "error")); 386 stream->close(); 387 388 EXPECT_EQ(ReadableStream::Errored, stream->state()); 389 isolate()->RunMicrotasks(); 390 391 EXPECT_TRUE(onFulfilled.isNull()); 392 EXPECT_EQ("NotFoundError: error", onRejected); 393} 394 395TEST_F(ReadableStreamTest, ReadWhenWaiting) 396{ 397 StringStream* stream = construct(); 398 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 399 EXPECT_FALSE(m_exceptionState.hadException()); 400 401 stream->read(scriptState(), m_exceptionState); 402 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 403 EXPECT_TRUE(m_exceptionState.hadException()); 404 EXPECT_EQ(V8TypeError, m_exceptionState.code()); 405 EXPECT_EQ("read is called while state is waiting", m_exceptionState.message()); 406} 407 408TEST_F(ReadableStreamTest, ReadWhenClosed) 409{ 410 StringStream* stream = construct(); 411 stream->close(); 412 413 EXPECT_EQ(ReadableStream::Closed, stream->state()); 414 EXPECT_FALSE(m_exceptionState.hadException()); 415 416 stream->read(scriptState(), m_exceptionState); 417 EXPECT_EQ(ReadableStream::Closed, stream->state()); 418 EXPECT_TRUE(m_exceptionState.hadException()); 419 EXPECT_EQ(V8TypeError, m_exceptionState.code()); 420 EXPECT_EQ("read is called while state is closed", m_exceptionState.message()); 421} 422 423TEST_F(ReadableStreamTest, ReadWhenErrored) 424{ 425 // DOMException values specified in the spec are different from enum values 426 // defined in ExceptionCode.h. 427 const int notFoundExceptionCode = 8; 428 StringStream* stream = construct(); 429 stream->error(DOMException::create(NotFoundError, "error")); 430 431 EXPECT_EQ(ReadableStream::Errored, stream->state()); 432 EXPECT_FALSE(m_exceptionState.hadException()); 433 434 stream->read(scriptState(), m_exceptionState); 435 EXPECT_EQ(ReadableStream::Errored, stream->state()); 436 EXPECT_TRUE(m_exceptionState.hadException()); 437 EXPECT_EQ(notFoundExceptionCode, m_exceptionState.code()); 438 EXPECT_EQ("error", m_exceptionState.message()); 439} 440 441TEST_F(ReadableStreamTest, EnqueuedAndRead) 442{ 443 StringStream* stream = construct(); 444 String onFulfilled, onRejected; 445 Checkpoint checkpoint; 446 447 { 448 InSequence s; 449 EXPECT_CALL(checkpoint, Call(0)); 450 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 451 EXPECT_CALL(checkpoint, Call(1)); 452 } 453 454 stream->enqueue("hello"); 455 ScriptPromise promise = stream->wait(scriptState()); 456 EXPECT_EQ(ReadableStream::Readable, stream->state()); 457 EXPECT_FALSE(stream->isPulling()); 458 459 checkpoint.Call(0); 460 String chunk; 461 EXPECT_TRUE(stream->read(scriptState(), m_exceptionState).toString(chunk)); 462 checkpoint.Call(1); 463 EXPECT_FALSE(m_exceptionState.hadException()); 464 EXPECT_EQ("hello", chunk); 465 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 466 EXPECT_TRUE(stream->isPulling()); 467 EXPECT_FALSE(stream->isDraining()); 468 469 ScriptPromise newPromise = stream->wait(scriptState()); 470 newPromise.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 471 isolate()->RunMicrotasks(); 472 EXPECT_NE(promise, newPromise); 473 EXPECT_TRUE(onFulfilled.isNull()); 474 EXPECT_TRUE(onRejected.isNull()); 475} 476 477TEST_F(ReadableStreamTest, EnqueTwiceAndRead) 478{ 479 StringStream* stream = construct(); 480 Checkpoint checkpoint; 481 482 { 483 InSequence s; 484 EXPECT_CALL(checkpoint, Call(0)); 485 EXPECT_CALL(checkpoint, Call(1)); 486 } 487 488 EXPECT_TRUE(stream->enqueue("hello")); 489 EXPECT_TRUE(stream->enqueue("bye")); 490 ScriptPromise promise = stream->wait(scriptState()); 491 EXPECT_EQ(ReadableStream::Readable, stream->state()); 492 EXPECT_FALSE(stream->isPulling()); 493 494 checkpoint.Call(0); 495 String chunk; 496 EXPECT_TRUE(stream->read(scriptState(), m_exceptionState).toString(chunk)); 497 checkpoint.Call(1); 498 EXPECT_FALSE(m_exceptionState.hadException()); 499 EXPECT_EQ("hello", chunk); 500 EXPECT_EQ(ReadableStream::Readable, stream->state()); 501 EXPECT_FALSE(stream->isPulling()); 502 EXPECT_FALSE(stream->isDraining()); 503 504 ScriptPromise newPromise = stream->wait(scriptState()); 505 EXPECT_EQ(promise, newPromise); 506} 507 508TEST_F(ReadableStreamTest, CloseWhenReadable) 509{ 510 StringStream* stream = construct(); 511 String onWaitFulfilled, onWaitRejected; 512 String onClosedFulfilled, onClosedRejected; 513 514 stream->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createCaptor(&onClosedRejected)); 515 EXPECT_TRUE(stream->enqueue("hello")); 516 EXPECT_TRUE(stream->enqueue("bye")); 517 stream->close(); 518 EXPECT_FALSE(stream->enqueue("should be ignored")); 519 520 ScriptPromise promise = stream->wait(scriptState()); 521 EXPECT_EQ(ReadableStream::Readable, stream->state()); 522 EXPECT_FALSE(stream->isPulling()); 523 EXPECT_TRUE(stream->isDraining()); 524 525 String chunk; 526 EXPECT_TRUE(stream->read(scriptState(), m_exceptionState).toString(chunk)); 527 EXPECT_EQ("hello", chunk); 528 EXPECT_EQ(promise, stream->wait(scriptState())); 529 530 isolate()->RunMicrotasks(); 531 532 EXPECT_EQ(ReadableStream::Readable, stream->state()); 533 EXPECT_FALSE(stream->isPulling()); 534 EXPECT_TRUE(stream->isDraining()); 535 536 EXPECT_TRUE(stream->read(scriptState(), m_exceptionState).toString(chunk)); 537 EXPECT_EQ("bye", chunk); 538 EXPECT_FALSE(m_exceptionState.hadException()); 539 540 EXPECT_NE(promise, stream->wait(scriptState())); 541 stream->wait(scriptState()).then(createCaptor(&onWaitFulfilled), createCaptor(&onWaitRejected)); 542 543 EXPECT_EQ(ReadableStream::Closed, stream->state()); 544 EXPECT_FALSE(stream->isPulling()); 545 EXPECT_TRUE(stream->isDraining()); 546 547 EXPECT_TRUE(onWaitFulfilled.isNull()); 548 EXPECT_TRUE(onWaitRejected.isNull()); 549 EXPECT_TRUE(onClosedFulfilled.isNull()); 550 EXPECT_TRUE(onClosedRejected.isNull()); 551 552 isolate()->RunMicrotasks(); 553 EXPECT_EQ("undefined", onWaitFulfilled); 554 EXPECT_TRUE(onWaitRejected.isNull()); 555 EXPECT_EQ("undefined", onClosedFulfilled); 556 EXPECT_TRUE(onClosedRejected.isNull()); 557} 558 559TEST_F(ReadableStreamTest, CancelWhenClosed) 560{ 561 StringStream* stream = construct(); 562 String onFulfilled, onRejected; 563 stream->close(); 564 EXPECT_EQ(ReadableStream::Closed, stream->state()); 565 566 ScriptPromise promise = stream->cancel(scriptState(), ScriptValue()); 567 EXPECT_EQ(ReadableStream::Closed, stream->state()); 568 569 promise.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 570 EXPECT_TRUE(onFulfilled.isNull()); 571 EXPECT_TRUE(onRejected.isNull()); 572 573 isolate()->RunMicrotasks(); 574 EXPECT_EQ("undefined", onFulfilled); 575 EXPECT_TRUE(onRejected.isNull()); 576} 577 578TEST_F(ReadableStreamTest, CancelWhenErrored) 579{ 580 StringStream* stream = construct(); 581 String onFulfilled, onRejected; 582 stream->error(DOMException::create(NotFoundError, "error")); 583 EXPECT_EQ(ReadableStream::Errored, stream->state()); 584 585 ScriptPromise promise = stream->cancel(scriptState(), ScriptValue()); 586 EXPECT_EQ(ReadableStream::Errored, stream->state()); 587 588 promise.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 589 EXPECT_TRUE(onFulfilled.isNull()); 590 EXPECT_TRUE(onRejected.isNull()); 591 592 isolate()->RunMicrotasks(); 593 EXPECT_TRUE(onFulfilled.isNull()); 594 EXPECT_EQ("NotFoundError: error", onRejected); 595} 596 597TEST_F(ReadableStreamTest, CancelWhenWaiting) 598{ 599 StringStream* stream = construct(); 600 String onFulfilled, onRejected; 601 ScriptValue reason(scriptState(), v8String(scriptState()->isolate(), "reason")); 602 ScriptPromise promise = ScriptPromise::cast(scriptState(), v8String(scriptState()->isolate(), "hello")); 603 604 { 605 InSequence s; 606 EXPECT_CALL(*m_underlyingSource, pullSource()).Times(1); 607 EXPECT_CALL(*m_underlyingSource, cancelSource(scriptState(), reason)).WillOnce(Return(promise)); 608 } 609 610 EXPECT_EQ(ReadableStream::Waiting, stream->state()); 611 ScriptPromise wait = stream->wait(scriptState()); 612 EXPECT_EQ(promise, stream->cancel(scriptState(), reason)); 613 EXPECT_EQ(ReadableStream::Closed, stream->state()); 614 EXPECT_EQ(stream->wait(scriptState()), wait); 615 616 wait.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 617 EXPECT_TRUE(onFulfilled.isNull()); 618 EXPECT_TRUE(onRejected.isNull()); 619 620 isolate()->RunMicrotasks(); 621 EXPECT_EQ("undefined", onFulfilled); 622 EXPECT_TRUE(onRejected.isNull()); 623} 624 625TEST_F(ReadableStreamTest, CancelWhenReadable) 626{ 627 StringStream* stream = construct(); 628 String onFulfilled, onRejected; 629 ScriptValue reason(scriptState(), v8String(scriptState()->isolate(), "reason")); 630 ScriptPromise promise = ScriptPromise::cast(scriptState(), v8String(scriptState()->isolate(), "hello")); 631 632 { 633 InSequence s; 634 EXPECT_CALL(*m_underlyingSource, cancelSource(scriptState(), reason)).WillOnce(Return(promise)); 635 } 636 637 stream->enqueue("hello"); 638 ScriptPromise wait = stream->wait(scriptState()); 639 EXPECT_EQ(ReadableStream::Readable, stream->state()); 640 EXPECT_EQ(promise, stream->cancel(scriptState(), reason)); 641 EXPECT_EQ(ReadableStream::Closed, stream->state()); 642 643 EXPECT_NE(stream->wait(scriptState()), wait); 644 645 stream->wait(scriptState()).then(createCaptor(&onFulfilled), createCaptor(&onRejected)); 646 EXPECT_TRUE(onFulfilled.isNull()); 647 EXPECT_TRUE(onRejected.isNull()); 648 649 isolate()->RunMicrotasks(); 650 EXPECT_EQ("undefined", onFulfilled); 651 EXPECT_TRUE(onRejected.isNull()); 652} 653 654TEST_F(ReadableStreamTest, ReadableArrayBufferCompileTest) 655{ 656 // This test tests if ReadableStreamImpl<ArrayBuffer> can be instantiated. 657 new ReadableStreamImpl<ReadableStreamChunkTypeTraits<ArrayBuffer> >(scriptState()->executionContext(), m_underlyingSource); 658} 659 660} // namespace blink 661 662