'use strict';

// These tests can be run against any readable stream produced by the web platform that meets the given descriptions.
// For readable stream tests, the factory should return the stream. For reader tests, the factory should return a
// { stream, reader } object. (You can use this to vary the time at which you acquire a reader.)

self.templatedRSEmpty = (label, factory) => {
  test(() => {}, 'Running templatedRSEmpty with ' + label);

  test(() => {

    const rs = factory();

    assert_equals(typeof rs.locked, 'boolean', 'has a boolean locked getter');
    assert_equals(typeof rs.cancel, 'function', 'has a cancel method');
    assert_equals(typeof rs.getReader, 'function', 'has a getReader method');
    assert_equals(typeof rs.pipeThrough, 'function', 'has a pipeThrough method');
    assert_equals(typeof rs.pipeTo, 'function', 'has a pipeTo method');
    assert_equals(typeof rs.tee, 'function', 'has a tee method');

  }, label + ': instances have the correct methods and properties');

  test(() => {
    const rs = factory();

    assert_throws(new RangeError(), () => rs.getReader({ mode: '' }), 'empty string mode should throw');
    assert_throws(new RangeError(), () => rs.getReader({ mode: null }), 'null mode should throw');
    assert_throws(new RangeError(), () => rs.getReader({ mode: 'asdf' }), 'asdf mode should throw');
    assert_throws(new TypeError(), () => rs.getReader(null), 'null should throw');

  }, label + ': calling getReader with invalid arguments should throw appropriate errors');
};

self.templatedRSClosed = (label, factory) => {
  test(() => {}, 'Running templatedRSClosed with ' + label);

  promise_test(() => {

    const rs = factory();
    const cancelPromise1 = rs.cancel();
    const cancelPromise2 = rs.cancel();

    assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');

    return Promise.all([
      cancelPromise1.then(v => assert_equals(v, undefined, 'first cancel() call should fulfill with undefined')),
      cancelPromise2.then(v => assert_equals(v, undefined, 'second cancel() call should fulfill with undefined'))
    ]);

  }, label + ': cancel() should return a distinct fulfilled promise each time');

  test(() => {

    const rs = factory();
    assert_false(rs.locked, 'locked getter should return false');

  }, label + ': locked should be false');

  test(() => {

    const rs = factory();
    rs.getReader(); // getReader() should not throw.

  }, label + ': getReader() should be OK');

  test(() => {

    const rs = factory();

    const reader = rs.getReader();
    reader.releaseLock();

    const reader2 = rs.getReader(); // Getting a second reader should not throw.
    reader2.releaseLock();

    rs.getReader(); // Getting a third reader should not throw.

  }, label + ': should be able to acquire multiple readers if they are released in succession');

  test(() => {

    const rs = factory();

    rs.getReader();

    assert_throws(new TypeError(), () => rs.getReader(), 'getting a second reader should throw');
    assert_throws(new TypeError(), () => rs.getReader(), 'getting a third reader should throw');

  }, label + ': should not be able to acquire a second reader if we don\'t release the first one');
};

self.templatedRSErrored = (label, factory, error) => {
  test(() => {}, 'Running templatedRSErrored with ' + label);

  promise_test(t => {

    const rs = factory();
    const reader = rs.getReader();

    return Promise.all([
      promise_rejects(t, error, reader.closed),
      promise_rejects(t, error, reader.read())
    ]);

  }, label + ': getReader() should return a reader that acts errored');

  promise_test(t => {

    const rs = factory();
    const reader = rs.getReader();

    return Promise.all([
      promise_rejects(t, error, reader.read()),
      promise_rejects(t, error, reader.read()),
      promise_rejects(t, error, reader.closed)
    ]);

  }, label + ': read() twice should give the error each time');

  test(() => {
    const rs = factory();

    assert_false(rs.locked, 'locked getter should return false');
  }, label + ': locked should be false');
};

self.templatedRSErroredSyncOnly = (label, factory, error) => {
  test(() => {}, 'Running templatedRSErroredSyncOnly with ' + label);

  promise_test(t => {

    const rs = factory();
    rs.getReader().releaseLock();
    const reader = rs.getReader(); // Calling getReader() twice does not throw (the stream is not locked).

    return promise_rejects(t, error, reader.closed);

  }, label + ': should be able to obtain a second reader, with the correct closed promise');

  test(() => {

    const rs = factory();
    rs.getReader();

    assert_throws(new TypeError(), () => rs.getReader(), 'getting a second reader should throw a TypeError');
    assert_throws(new TypeError(), () => rs.getReader(), 'getting a third reader should throw a TypeError');

  }, label + ': should not be able to obtain additional readers if we don\'t release the first lock');

  promise_test(t => {

    const rs = factory();
    const cancelPromise1 = rs.cancel();
    const cancelPromise2 = rs.cancel();

    assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');

    return Promise.all([
      promise_rejects(t, error, cancelPromise1),
      promise_rejects(t, error, cancelPromise2)
    ]);

  }, label + ': cancel() should return a distinct rejected promise each time');

  promise_test(t => {

    const rs = factory();
    const reader = rs.getReader();
    const cancelPromise1 = reader.cancel();
    const cancelPromise2 = reader.cancel();

    assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');

    return Promise.all([
      promise_rejects(t, error, cancelPromise1),
      promise_rejects(t, error, cancelPromise2)
    ]);

  }, label + ': reader cancel() should return a distinct rejected promise each time');
};

self.templatedRSEmptyReader = (label, factory) => {
  test(() => {}, 'Running templatedRSEmptyReader with ' + label);

  test(() => {

    const reader = factory().reader;

    assert_true('closed' in reader, 'has a closed property');
    assert_equals(typeof reader.closed.then, 'function', 'closed property is thenable');

    assert_equals(typeof reader.cancel, 'function', 'has a cancel method');
    assert_equals(typeof reader.read, 'function', 'has a read method');
    assert_equals(typeof reader.releaseLock, 'function', 'has a releaseLock method');

  }, label + ': instances have the correct methods and properties');

  test(() => {

    const stream = factory().stream;

    assert_true(stream.locked, 'locked getter should return true');

  }, label + ': locked should be true');

  promise_test(t => {

    const reader = factory().reader;

    reader.read().then(
      t.unreached_func('read() should not fulfill'),
      t.unreached_func('read() should not reject')
    );

    return delay(500);

  }, label + ': read() should never settle');

  promise_test(t => {

    const reader = factory().reader;

    reader.read().then(
      t.unreached_func('read() should not fulfill'),
      t.unreached_func('read() should not reject')
    );

    reader.read().then(
      t.unreached_func('read() should not fulfill'),
      t.unreached_func('read() should not reject')
    );

    return delay(500);

  }, label + ': two read()s should both never settle');

  test(() => {

    const reader = factory().reader;
    assert_not_equals(reader.read(), reader.read(), 'the promises returned should be distinct');

  }, label + ': read() should return distinct promises each time');

  test(() => {

    const stream = factory().stream;
    assert_throws(new TypeError(), () => stream.getReader(), 'stream.getReader() should throw a TypeError');

  }, label + ': getReader() again on the stream should fail');

  promise_test(t => {

    const streamAndReader = factory();
    const stream = streamAndReader.stream;
    const reader = streamAndReader.reader;

    reader.read().then(
      t.unreached_func('first read() should not fulfill'),
      t.unreached_func('first read() should not reject')
    );

    reader.read().then(
      t.unreached_func('second read() should not fulfill'),
      t.unreached_func('second read() should not reject')
    );

    reader.closed.then(
      t.unreached_func('closed should not fulfill'),
      t.unreached_func('closed should not reject')
    );

    assert_throws(new TypeError(), () => reader.releaseLock(), 'releaseLock should throw a TypeError');

    assert_true(stream.locked, 'the stream should still be locked');

    return delay(500);

  }, label + ': releasing the lock with pending read requests should throw but the read requests should stay pending');

  promise_test(t => {

    const reader = factory().reader;
    reader.releaseLock();

    return Promise.all([
      promise_rejects(t, new TypeError(), reader.read()),
      promise_rejects(t, new TypeError(), reader.read())
    ]);

  }, label + ': releasing the lock should cause further read() calls to reject with a TypeError');

  promise_test(t => {

    const reader = factory().reader;

    const closedBefore = reader.closed;
    reader.releaseLock();
    const closedAfter = reader.closed;

    assert_equals(closedBefore, closedAfter, 'the closed promise should not change identity');

    return promise_rejects(t, new TypeError(), closedBefore);

  }, label + ': releasing the lock should cause closed calls to reject with a TypeError');

  test(() => {

    const streamAndReader = factory();
    const stream = streamAndReader.stream;
    const reader = streamAndReader.reader;

    reader.releaseLock();
    assert_false(stream.locked, 'locked getter should return false');

  }, label + ': releasing the lock should cause locked to become false');

  promise_test(() => {

    const reader = factory().reader;
    reader.cancel();

    return reader.read().then(r => {
      assert_object_equals(r, { value: undefined, done: true }, 'read()ing from the reader should give a done result');
    });

  }, label + ': canceling via the reader should cause the reader to act closed');

  promise_test(t => {

    const stream = factory().stream;
    return promise_rejects(t, new TypeError(), stream.cancel());

  }, label + ': canceling via the stream should fail');
};

self.templatedRSClosedReader = (label, factory) => {
  test(() => {}, 'Running templatedRSClosedReader with ' + label);

  promise_test(() => {

    const reader = factory().reader;

    return reader.read().then(v => {
      assert_object_equals(v, { value: undefined, done: true }, 'read() should fulfill correctly');
    });

  }, label + ': read() should fulfill with { value: undefined, done: true }');

  promise_test(() => {

    const reader = factory().reader;

    return Promise.all([
      reader.read().then(v => {
        assert_object_equals(v, { value: undefined, done: true }, 'read() should fulfill correctly');
      }),
      reader.read().then(v => {
        assert_object_equals(v, { value: undefined, done: true }, 'read() should fulfill correctly');
      })
    ]);

  }, label + ': read() multiple times should fulfill with { value: undefined, done: true }');

  promise_test(() => {

    const reader = factory().reader;

    return reader.read().then(() => reader.read()).then(v => {
      assert_object_equals(v, { value: undefined, done: true }, 'read() should fulfill correctly');
    });

  }, label + ': read() should work when used within another read() fulfill callback');

  promise_test(() => {

    const reader = factory().reader;

    return reader.closed.then(v => assert_equals(v, undefined, 'reader closed should fulfill with undefined'));

  }, label + ': closed should fulfill with undefined');

  promise_test(t => {

    const reader = factory().reader;

    const closedBefore = reader.closed;
    reader.releaseLock();
    const closedAfter = reader.closed;

    assert_not_equals(closedBefore, closedAfter, 'the closed promise should change identity');

    return Promise.all([
      closedBefore.then(v => assert_equals(v, undefined, 'reader.closed acquired before release should fulfill')),
      promise_rejects(t, new TypeError(), closedAfter)
    ]);

  }, label + ': releasing the lock should cause closed to reject and change identity');

  promise_test(() => {

    const reader = factory().reader;
    const cancelPromise1 = reader.cancel();
    const cancelPromise2 = reader.cancel();
    const closedReaderPromise = reader.closed;

    assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');
    assert_not_equals(cancelPromise1, closedReaderPromise, 'cancel() promise 1 should be distinct from reader.closed');
    assert_not_equals(cancelPromise2, closedReaderPromise, 'cancel() promise 2 should be distinct from reader.closed');

    return Promise.all([
      cancelPromise1.then(v => assert_equals(v, undefined, 'first cancel() should fulfill with undefined')),
      cancelPromise2.then(v => assert_equals(v, undefined, 'second cancel() should fulfill with undefined'))
    ]);

  }, label + ': cancel() should return a distinct fulfilled promise each time');
};

self.templatedRSErroredReader = (label, factory, error) => {
  test(() => {}, 'Running templatedRSErroredReader with ' + label);

  promise_test(t => {

    const reader = factory().reader;
    return promise_rejects(t, error, reader.closed);

  }, label + ': closed should reject with the error');

  promise_test(t => {

    const reader = factory().reader;
    const closedBefore = reader.closed;

    return promise_rejects(t, error, closedBefore).then(() => {
      reader.releaseLock();

      const closedAfter = reader.closed;
      assert_not_equals(closedBefore, closedAfter, 'the closed promise should change identity');

      return promise_rejects(t, new TypeError(), closedAfter);
    });

  }, label + ': releasing the lock should cause closed to reject and change identity');

  promise_test(t => {

    const reader = factory().reader;
    return promise_rejects(t, error, reader.read());

  }, label + ': read() should reject with the error');
};

self.templatedRSTwoChunksOpenReader = (label, factory, chunks) => {
  test(() => {}, 'Running templatedRSTwoChunksOpenReader with ' + label);

  promise_test(() => {

    const reader = factory().reader;

    return Promise.all([
      reader.read().then(r => {
        assert_object_equals(r, { value: chunks[0], done: false }, 'first result should be correct');
      }),
      reader.read().then(r => {
        assert_object_equals(r, { value: chunks[1], done: false }, 'second result should be correct');
      })
    ]);

  }, label + ': calling read() twice without waiting will eventually give both chunks (sequential)');

  promise_test(() => {

    const reader = factory().reader;

    return reader.read().then(r => {
      assert_object_equals(r, { value: chunks[0], done: false }, 'first result should be correct');

      return reader.read().then(r2 => {
        assert_object_equals(r2, { value: chunks[1], done: false }, 'second result should be correct');
      });
    });

  }, label + ': calling read() twice without waiting will eventually give both chunks (nested)');

  test(() => {

    const reader = factory().reader;
    assert_not_equals(reader.read(), reader.read(), 'the promises returned should be distinct');

  }, label + ': read() should return distinct promises each time');

  promise_test(() => {

    const reader = factory().reader;

    const promise1 = reader.closed.then(v => {
      assert_equals(v, undefined, 'reader closed should fulfill with undefined');
    });

    const promise2 = reader.read().then(r => {
      assert_object_equals(r, { value: chunks[0], done: false },
                           'promise returned before cancellation should fulfill with a chunk');
    });

    reader.cancel();

    const promise3 = reader.read().then(r => {
      assert_object_equals(r, { value: undefined, done: true },
                           'promise returned after cancellation should fulfill with an end-of-stream signal');
    });

    return Promise.all([promise1, promise2, promise3]);

  }, label + ': cancel() after a read() should still give that single read result');
};

self.templatedRSTwoChunksClosedReader = function (label, factory, chunks) {
  test(() => {}, 'Running templatedRSTwoChunksClosedReader with ' + label);

  promise_test(() => {

    const reader = factory().reader;

    return Promise.all([
      reader.read().then(r => {
        assert_object_equals(r, { value: chunks[0], done: false }, 'first result should be correct');
      }),
      reader.read().then(r => {
        assert_object_equals(r, { value: chunks[1], done: false }, 'second result should be correct');
      }),
      reader.read().then(r => {
        assert_object_equals(r, { value: undefined, done: true }, 'third result should be correct');
      })
    ]);

  }, label + ': third read(), without waiting, should give { value: undefined, done: true } (sequential)');

  promise_test(() => {

    const reader = factory().reader;

    return reader.read().then(r => {
      assert_object_equals(r, { value: chunks[0], done: false }, 'first result should be correct');

      return reader.read().then(r2 => {
        assert_object_equals(r2, { value: chunks[1], done: false }, 'second result should be correct');

        return reader.read().then(r3 => {
          assert_object_equals(r3, { value: undefined, done: true }, 'third result should be correct');
        });
      });
    });

  }, label + ': third read(), without waiting, should give { value: undefined, done: true } (nested)');

  promise_test(() => {

    const streamAndReader = factory();
    const stream = streamAndReader.stream;
    const reader = streamAndReader.reader;

    assert_true(stream.locked, 'stream should start locked');

    const promise = reader.closed.then(v => {
      assert_equals(v, undefined, 'reader closed should fulfill with undefined');
      assert_true(stream.locked, 'stream should remain locked');
    });

    reader.read();
    reader.read();

    return promise;

  }, label +
     ': draining the stream via read() should cause the reader closed promise to fulfill, but locked stays true');

  promise_test(() => {

    const streamAndReader = factory();
    const stream = streamAndReader.stream;
    const reader = streamAndReader.reader;

    const promise = reader.closed.then(() => {
      assert_true(stream.locked, 'the stream should start locked');
      reader.releaseLock(); // Releasing the lock after reader closed should not throw.
      assert_false(stream.locked, 'the stream should end unlocked');
    });

    reader.read();
    reader.read();

    return promise;

  }, label + ': releasing the lock after the stream is closed should cause locked to become false');

  promise_test(t => {

    const reader = factory().reader;

    reader.releaseLock();

    return Promise.all([
      promise_rejects(t, new TypeError(), reader.read()),
      promise_rejects(t, new TypeError(), reader.read()),
      promise_rejects(t, new TypeError(), reader.read())
    ]);

  }, label + ': releasing the lock should cause further read() calls to reject with a TypeError');

  promise_test(() => {

    const streamAndReader = factory();
    const stream = streamAndReader.stream;
    const reader = streamAndReader.reader;

    const readerClosed = reader.closed;

    assert_equals(reader.closed, readerClosed, 'accessing reader.closed twice in succession gives the same value');

    const promise = reader.read().then(() => {
      assert_equals(reader.closed, readerClosed, 'reader.closed is the same after read() fulfills');

      reader.releaseLock();

      assert_equals(reader.closed, readerClosed, 'reader.closed is the same after releasing the lock');

      const newReader = stream.getReader();
      return newReader.read();
    });

    assert_equals(reader.closed, readerClosed, 'reader.closed is the same after calling read()');

    return promise;

  }, label + ': reader\'s closed property always returns the same promise');
};
