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