-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: takeWhileStreamFactory 개발 (#28)
Merge pull request #28 from daengdaengLee/issue-14
- Loading branch information
Showing
10 changed files
with
245 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,62 @@ | ||
import { Readable, PassThrough } from "node:stream"; | ||
import { Readable } from "node:stream"; | ||
import { pipeline } from "node:stream/promises"; | ||
import { takeStreamFactory } from "./take-stream-factory.js"; | ||
import { asyncInputs } from "./test-util/async-inputs.js"; | ||
import { sourceStreamCloseTestTemplate } from "./test-util/source-stream-close-test-template.js"; | ||
import { syncInputs } from "./test-util/sync-inputs.js"; | ||
import { ToArrayStream } from "./to-array-stream.js"; | ||
|
||
describe(`TakeStreamFactory Test`, () => { | ||
const n = 2; | ||
const inputs = [1, 2, 3, 4, 5, 6]; | ||
describe(`takeStreamFactory Test`, () => { | ||
const n = 4; | ||
const expected = [1, 2, 3, 4]; | ||
const testCases = [ | ||
{ name: `sync data`, inputs: syncInputs }, | ||
{ name: `async data`, inputs: asyncInputs }, | ||
]; | ||
|
||
describe(`outputs only the number you set and exits.`, () => { | ||
it(`no currey version`, async () => { | ||
const outputs: Array<number> = []; | ||
await pipeline( | ||
takeStreamFactory({ n: n }, Readable.from(inputs)), | ||
new ToArrayStream({ target: outputs }, { objectMode: true }), | ||
); | ||
|
||
expect(outputs).toEqual(inputs.slice(0, n)); | ||
}); | ||
|
||
it(`currey version`, async () => { | ||
const outputs: Array<number> = []; | ||
await pipeline( | ||
takeStreamFactory({ n: n })(Readable.from(inputs)), | ||
new ToArrayStream({ target: outputs }, { objectMode: true }), | ||
); | ||
|
||
expect(outputs).toEqual(inputs.slice(0, n)); | ||
}); | ||
}); | ||
|
||
describe(`close source stream after at most n data yields`, () => { | ||
it(`no curry version`, async () => { | ||
const sourceOutputs: Array<number> = []; | ||
let sourceDone = false; | ||
const sourceStream = Readable.from(inputs); | ||
sourceStream.on(`data`, (value) => { | ||
sourceOutputs.push(value); | ||
for (const { name, inputs } of testCases) { | ||
describe(name, () => { | ||
it(`no currey version`, async () => { | ||
const outputs: Array<number> = []; | ||
await pipeline( | ||
takeStreamFactory({ n: n }, Readable.from(inputs())), | ||
new ToArrayStream({ target: outputs }, { objectMode: true }), | ||
); | ||
expect(outputs).toEqual(expected); | ||
}); | ||
|
||
it(`currey version`, async () => { | ||
const outputs: Array<number> = []; | ||
await pipeline( | ||
takeStreamFactory({ n: n })(Readable.from(inputs())), | ||
new ToArrayStream({ target: outputs }, { objectMode: true }), | ||
); | ||
expect(outputs).toEqual(expected); | ||
}); | ||
}); | ||
sourceStream.on(`close`, () => { | ||
sourceDone = true; | ||
}); | ||
await pipeline( | ||
takeStreamFactory({ n: n }, sourceStream), | ||
new PassThrough({ objectMode: true }), | ||
); | ||
|
||
expect(sourceOutputs).toEqual(inputs.slice(0, n)); | ||
expect(sourceDone).toBeTruthy(); | ||
}); | ||
} | ||
}); | ||
|
||
it(`curry version`, async () => { | ||
const sourceOutputs: Array<number> = []; | ||
let sourceDone = false; | ||
const sourceStream = Readable.from(inputs); | ||
sourceStream.on(`data`, (value) => { | ||
sourceOutputs.push(value); | ||
describe(`close source stream when close wrapped stream.`, () => { | ||
for (const { name, inputs } of testCases) { | ||
describe(name, () => { | ||
it(`no curry version`, async () => { | ||
const sourceStream = Readable.from(inputs()); | ||
const wrappedStream = Readable.from( | ||
takeStreamFactory({ n: n }, sourceStream), | ||
); | ||
await sourceStreamCloseTestTemplate(sourceStream, wrappedStream); | ||
}); | ||
|
||
it(`curry version`, async () => { | ||
const sourceStream = Readable.from(inputs()); | ||
const wrappedStream = Readable.from( | ||
takeStreamFactory({ n: n })(sourceStream), | ||
); | ||
await sourceStreamCloseTestTemplate(sourceStream, wrappedStream); | ||
}); | ||
}); | ||
sourceStream.on(`close`, () => { | ||
sourceDone = true; | ||
}); | ||
await pipeline( | ||
takeStreamFactory({ n: n })(sourceStream), | ||
new PassThrough({ objectMode: true }), | ||
); | ||
|
||
expect(sourceOutputs).toEqual(inputs.slice(0, n)); | ||
expect(sourceDone).toBeTruthy(); | ||
}); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Readable } from "node:stream"; | ||
import { pipeline } from "node:stream/promises"; | ||
import { takeWhileStreamFactory } from "./take-while-stream-factory.js"; | ||
import { asyncInputs } from "./test-util/async-inputs.js"; | ||
import { sourceStreamCloseTestTemplate } from "./test-util/source-stream-close-test-template.js"; | ||
import { syncInputs } from "./test-util/sync-inputs.js"; | ||
import { ToArrayStream } from "./to-array-stream.js"; | ||
import { delay } from "./util.js"; | ||
|
||
describe(`takeWhileStreamFactory Test`, () => { | ||
const syncF = (n: number): boolean => { | ||
return n < 5; | ||
}; | ||
const asyncF = async (n: number): Promise<boolean> => { | ||
await delay(100); | ||
return syncF(n); | ||
}; | ||
const expected: Array<number> = [1, 2, 3, 4]; | ||
const testCases = [ | ||
{ name: `sync data + sync predicate`, f: syncF, inputs: syncInputs }, | ||
{ name: `sync data + async predicate`, f: asyncF, inputs: syncInputs }, | ||
{ name: `async data + sync predicate`, f: syncF, inputs: asyncInputs }, | ||
{ name: `async data + async predicate`, f: asyncF, inputs: asyncInputs }, | ||
]; | ||
|
||
describe(`outputs while the predicate function returns true and exits.`, () => { | ||
for (const { name, f, inputs } of testCases) { | ||
describe(name, () => { | ||
it(`no curry version`, async () => { | ||
const outputs: Array<number> = []; | ||
await pipeline( | ||
takeWhileStreamFactory({ f: f }, Readable.from(inputs())), | ||
new ToArrayStream({ target: outputs }, { objectMode: true }), | ||
); | ||
expect(outputs).toEqual(expected); | ||
}); | ||
|
||
it(`curry version`, async () => { | ||
const outputs: Array<number> = []; | ||
await pipeline( | ||
takeWhileStreamFactory({ f: f })(Readable.from(inputs())), | ||
new ToArrayStream({ target: outputs }, { objectMode: true }), | ||
); | ||
expect(outputs).toEqual(expected); | ||
}); | ||
}); | ||
} | ||
}); | ||
|
||
describe(`close source stream when close wrapped stream.`, () => { | ||
for (const { name, f, inputs } of testCases) { | ||
describe(name, () => { | ||
it(`no curry version`, async () => { | ||
const sourceStream = Readable.from(inputs()); | ||
const wrappedStream = Readable.from( | ||
takeWhileStreamFactory({ f: f }, sourceStream), | ||
); | ||
await sourceStreamCloseTestTemplate(sourceStream, wrappedStream); | ||
}); | ||
|
||
it(`curry version`, async () => { | ||
const sourceStream = Readable.from(inputs()); | ||
const wrappedStream = Readable.from( | ||
takeWhileStreamFactory({ f: f })(sourceStream), | ||
); | ||
await sourceStreamCloseTestTemplate(sourceStream, wrappedStream); | ||
}); | ||
}); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
type Predicate<T> = (value: T) => boolean | Promise<boolean>; | ||
type Options<T> = { f: Predicate<T> }; | ||
type Stream<T> = Iterable<T> | AsyncIterable<T>; | ||
type Result<T> = AsyncGenerator<T>; | ||
|
||
export function takeWhileStreamFactory<T>( | ||
options: Options<T>, | ||
): (stream: Stream<T>) => Result<T>; | ||
export function takeWhileStreamFactory<T>( | ||
options: Options<T>, | ||
stream: Stream<T>, | ||
): Result<T>; | ||
export function takeWhileStreamFactory<T>( | ||
options: Options<T>, | ||
stream?: Stream<T>, | ||
): ((stream: Stream<T>) => Result<T>) | Result<T> { | ||
if (stream != null) { | ||
return _takeWhileStreamFactory(options, stream); | ||
} | ||
|
||
return (stream: Stream<T>): Result<T> => { | ||
return _takeWhileStreamFactory(options, stream); | ||
}; | ||
} | ||
|
||
async function* _takeWhileStreamFactory<T>( | ||
options: Options<T>, | ||
stream: Stream<T>, | ||
): Result<T> { | ||
for await (const value of stream) { | ||
const isEnd = !(await options.f(value)); | ||
if (isEnd) { | ||
return; | ||
} | ||
yield value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { delay } from "../util.js"; | ||
import { syncInputs } from "./sync-inputs.js"; | ||
|
||
export async function* asyncInputs() { | ||
for (const n of syncInputs()) { | ||
await delay(50); | ||
yield n; | ||
await delay(50); | ||
} | ||
} |
Oops, something went wrong.