diff options
Diffstat (limited to 'cli/js/tests/streams_writable_test.ts')
-rw-r--r-- | cli/js/tests/streams_writable_test.ts | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/cli/js/tests/streams_writable_test.ts b/cli/js/tests/streams_writable_test.ts new file mode 100644 index 000000000..54c1624af --- /dev/null +++ b/cli/js/tests/streams_writable_test.ts @@ -0,0 +1,253 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { unitTest, assert, assertEquals, assertThrows } from "./test_util.ts"; + +unitTest(function writableStreamDesiredSizeOnReleasedWriter() { + const ws = new WritableStream(); + const writer = ws.getWriter(); + writer.releaseLock(); + assertThrows(() => { + writer.desiredSize; + }, TypeError); +}); + +unitTest(function writableStreamDesiredSizeInitialValue() { + const ws = new WritableStream(); + const writer = ws.getWriter(); + assertEquals(writer.desiredSize, 1); +}); + +unitTest(async function writableStreamDesiredSizeClosed() { + const ws = new WritableStream(); + const writer = ws.getWriter(); + await writer.close(); + assertEquals(writer.desiredSize, 0); +}); + +unitTest(function writableStreamStartThrowsDesiredSizeNull() { + const ws = new WritableStream({ + start(c): void { + c.error(); + }, + }); + + const writer = ws.getWriter(); + assertEquals(writer.desiredSize, null, "desiredSize should be null"); +}); + +unitTest(function getWriterOnClosingStream() { + const ws = new WritableStream({}); + + const writer = ws.getWriter(); + writer.close(); + writer.releaseLock(); + + ws.getWriter(); +}); + +unitTest(async function getWriterOnClosedStream() { + const ws = new WritableStream({}); + + const writer = ws.getWriter(); + await writer.close(); + writer.releaseLock(); + + ws.getWriter(); +}); + +unitTest(function getWriterOnAbortedStream() { + const ws = new WritableStream({}); + + const writer = ws.getWriter(); + writer.abort(); + writer.releaseLock(); + + ws.getWriter(); +}); + +unitTest(function getWriterOnErroredStream() { + const ws = new WritableStream({ + start(c): void { + c.error(); + }, + }); + + const writer = ws.getWriter(); + return writer.closed.then( + (v) => { + throw new Error(`writer.closed fulfilled unexpectedly with: ${v}`); + }, + () => { + writer.releaseLock(); + ws.getWriter(); + } + ); +}); + +unitTest(function closedAndReadyOnReleasedWriter() { + const ws = new WritableStream({}); + + const writer = ws.getWriter(); + writer.releaseLock(); + + return writer.closed.then( + (v) => { + throw new Error("writer.closed fulfilled unexpectedly with: " + v); + }, + (closedRejection) => { + assertEquals( + closedRejection.name, + "TypeError", + "closed promise should reject with a TypeError" + ); + return writer.ready.then( + (v) => { + throw new Error("writer.ready fulfilled unexpectedly with: " + v); + }, + (readyRejection) => + assertEquals( + readyRejection, + closedRejection, + "ready promise should reject with the same error" + ) + ); + } + ); +}); + +unitTest(function sinkMethodsCalledAsMethods() { + let thisObject: Sink | null = null; + // Calls to Sink methods after the first are implicitly ignored. Only the + // first value that is passed to the resolver is used. + class Sink { + start(): void { + assertEquals(this, thisObject, "start should be called as a method"); + } + + write(): void { + assertEquals(this, thisObject, "write should be called as a method"); + } + + close(): void { + assertEquals(this, thisObject, "close should be called as a method"); + } + + abort(): void { + assertEquals(this, thisObject, "abort should be called as a method"); + } + } + + const theSink = new Sink(); + thisObject = theSink; + const ws = new WritableStream(theSink); + + const writer = ws.getWriter(); + + writer.write("a"); + const closePromise = writer.close(); + + const ws2 = new WritableStream(theSink); + const writer2 = ws2.getWriter(); + const abortPromise = writer2.abort(); + + return Promise.all([closePromise, abortPromise]).then(undefined); +}); + +unitTest(function sizeShouldNotBeCalledAsMethod() { + const strategy = { + size(): number { + if (this !== undefined) { + throw new Error("size called as a method"); + } + return 1; + }, + }; + + const ws = new WritableStream({}, strategy); + const writer = ws.getWriter(); + return writer.write("a"); +}); + +unitTest(function redundantReleaseLockIsNoOp() { + const ws = new WritableStream(); + const writer1 = ws.getWriter(); + assertEquals( + undefined, + writer1.releaseLock(), + "releaseLock() should return undefined" + ); + const writer2 = ws.getWriter(); + assertEquals( + undefined, + writer1.releaseLock(), + "no-op releaseLock() should return undefined" + ); + // Calling releaseLock() on writer1 should not interfere with writer2. If it did, then the ready promise would be + // rejected. + return writer2.ready; +}); + +unitTest(function readyPromiseShouldFireBeforeReleaseLock() { + const events: string[] = []; + const ws = new WritableStream(); + const writer = ws.getWriter(); + return writer.ready.then(() => { + // Force the ready promise back to a pending state. + const writerPromise = writer.write("dummy"); + const readyPromise = writer.ready.catch(() => events.push("ready")); + const closedPromise = writer.closed.catch(() => events.push("closed")); + writer.releaseLock(); + return Promise.all([readyPromise, closedPromise]).then(() => { + assertEquals( + events, + ["ready", "closed"], + "ready promise should fire before closed promise" + ); + // Stop the writer promise hanging around after the test has finished. + return Promise.all([writerPromise, ws.abort()]).then(undefined); + }); + }); +}); + +unitTest(function subclassingWritableStream() { + class Subclass extends WritableStream { + extraFunction(): boolean { + return true; + } + } + assert( + Object.getPrototypeOf(Subclass.prototype) === WritableStream.prototype, + "Subclass.prototype's prototype should be WritableStream.prototype" + ); + assert( + Object.getPrototypeOf(Subclass) === WritableStream, + "Subclass's prototype should be WritableStream" + ); + const sub = new Subclass(); + assert( + sub instanceof WritableStream, + "Subclass object should be an instance of WritableStream" + ); + assert( + sub instanceof Subclass, + "Subclass object should be an instance of Subclass" + ); + const lockedGetter = Object.getOwnPropertyDescriptor( + WritableStream.prototype, + "locked" + )!.get!; + assert( + lockedGetter.call(sub) === sub.locked, + "Subclass object should pass brand check" + ); + assert( + sub.extraFunction(), + "extraFunction() should be present on Subclass object" + ); +}); + +unitTest(function lockedGetterShouldReturnTrue() { + const ws = new WritableStream(); + assert(!ws.locked, "stream should not be locked"); + ws.getWriter(); + assert(ws.locked, "stream should be locked"); +}); |