<!DOCTYPE html>
<script src='../../resources/testharness.js'></script>
<script src='../../resources/testharnessreport.js'></script>
<script src='resources/streams-utils.js'></script>
<script>
// This is updated till https://github.com/whatwg/streams/commit/4ba861e6f60c248060811830e11271c84b439cc3

test(function() {
    new WritableStream({}, new CountQueuingStrategy({ highWaterMark: 4 })); // Does not throw.
}, 'Can construct a writable stream with a valid CountQueuingStrategy');

var test1 = async_test('Correctly governs the value of a WritableStream\'s state property (HWM = 0)');
test1.step(function() {
    var dones = Object.create(null);

    var ws = new WritableStream(
        {
            write: function(chunk) {
                return new Promise(test1.step_func(function(resolve) { dones[chunk] = resolve; }));
            }
        },
        new CountQueuingStrategy({ highWaterMark: 0 })
    );

    setTimeout(test1.step_func(function() {
        assert_equals(ws.state, 'writable', 'After 0 writes, 0 of which finished, state should be \'writable\'');

        var writePromiseA = ws.write('a');
        assert_equals(ws.state, 'waiting', 'After 1 write, 0 of which finished, state should be \'waiting\'');

        var writePromiseB = ws.write('b');
        assert_equals(ws.state, 'waiting', 'After 2 writes, 0 of which finished, state should be \'waiting\'');

        dones.a();
        writePromiseA.then(test1.step_func(function() {
            assert_equals(ws.state, 'waiting', 'After 2 writes, 1 of which finished, state should be \'waiting\'');

            dones.b();
            return writePromiseB.then(test1.step_func(function() {
                assert_equals(ws.state, 'writable', 'After 2 writes, 2 of which finished, state should be \'writable\'');

                var writePromiseC = ws.write('c');
                assert_equals(ws.state, 'waiting', 'After 3 writes, 2 of which finished, state should be \'waiting\'');

                dones.c();
                return writePromiseC.then(test1.step_func(function() {
                    assert_equals(ws.state, 'writable', 'After 3 writes, 3 of which finished, state should be \'writable\'');

                    test1.done();
                }));
            }));
        })).catch(test1.step_func(function(e) { assert_unreached("uncaught error " + e); }));
    }), 0);
});

var test2 = async_test('Correctly governs the value of a WritableStream\'s state property (HWM = 4)');
test2.step(function() {
    var dones = Object.create(null);

    var ws = new WritableStream(
        {
            write: function(chunk) {
                return new Promise(test2.step_func(function(resolve) { dones[chunk] = resolve; }));
            }
        },
        new CountQueuingStrategy({ highWaterMark: 4 })
    );

    setTimeout(test2.step_func(function() {
        assert_equals(ws.state, 'writable', 'After 0 writes, 0 of which finished, state should be \'writable\'');

        var writePromiseA = ws.write('a');
        assert_equals(ws.state, 'writable', 'After 1 write, 0 of which finished, state should be \'writable\'');

        var writePromiseB = ws.write('b');
        assert_equals(ws.state, 'writable', 'After 2 writes, 0 of which finished, state should be \'writable\'');

        var writePromiseC = ws.write('c');
        assert_equals(ws.state, 'writable', 'After 3 writes, 0 of which finished, state should be \'writable\'');

        var writePromiseD = ws.write('d');
        assert_equals(ws.state, 'writable', 'After 4 writes, 0 of which finished, state should be \'writable\'');

        ws.write('e');
        assert_equals(ws.state, 'waiting', 'After 5 writes, 0 of which finished, state should be \'waiting\'');

        ws.write('f');
        assert_equals(ws.state, 'waiting', 'After 6 writes, 0 of which finished, state should be \'waiting\'');

        ws.write('g');
        assert_equals(ws.state, 'waiting', 'After 7 writes, 0 of which finished, state should be \'waiting\'');

        dones.a();
        writePromiseA.then(test2.step_func(function() {
            assert_equals(ws.state, 'waiting', 'After 7 writes, 1 of which finished, state should be \'waiting\'');

            dones.b();
            return writePromiseB.then(test2.step_func(function() {
                assert_equals(ws.state, 'waiting', 'After 7 writes, 2 of which finished, state should be \'waiting\'');

                dones.c();
                return writePromiseC.then(test2.step_func(function() {
                    assert_equals(ws.state, 'writable', 'After 7 writes, 3 of which finished, state should be \'writable\'');

                    ws.write('h');
                    assert_equals(ws.state, 'waiting', 'After 8 writes, 3 of which finished, state should be \'waiting\'');

                    dones.d();
                    return writePromiseD.then(test2.step_func(function() {
                        assert_equals(ws.state, 'writable', 'After 8 writes, 4 of which finished, state should be \'writable\'');

                        ws.write('i');
                        assert_equals(ws.state, 'waiting', 'After 9 writes, 4 of which finished, state should be \'waiting\'');

                        test2.done();
                    }));
                }));
            }));
        })).catch(test2.step_func(function(e) { assert_unreached("uncaught error " + e); }));
    }), 0);
});
</script>
