diff --git a/packages/csv-generate/lib/api/read.js b/packages/csv-generate/lib/api/read.js index 8d7b63b85..f1de454ea 100644 --- a/packages/csv-generate/lib/api/read.js +++ b/packages/csv-generate/lib/api/read.js @@ -5,8 +5,15 @@ const read = (options, state, size, push, close) => { // Get remaining buffer when fixedSize is enable if (options.fixedSize) { recordsLength = state.fixed_size_buffer.length; + if (size > 0 && recordsLength > size) { + const chunk = state.fixed_size_buffer.substr(0, size); + state.fixed_size_buffer = state.fixed_size_buffer.substr(size); + push(chunk); + return; + } if (recordsLength !== 0) { data.push(state.fixed_size_buffer); + state.fixed_size_buffer = ""; } } // eslint-disable-next-line diff --git a/packages/csv-generate/test/options.fixed_size.js b/packages/csv-generate/test/options.fixed_size.js index 16a08934b..f1528101b 100644 --- a/packages/csv-generate/test/options.fixed_size.js +++ b/packages/csv-generate/test/options.fixed_size.js @@ -1,7 +1,59 @@ import "should"; import { generate } from "../lib/index.js"; +import { generate as generateSync } from "../lib/sync.js"; describe("Option `fixed_size`", function () { + it("emits the final buffered suffix only once", function () { + generateSync({ + columns: [() => "abc"], + length: 1, + fixed_size: true, + highWaterMark: 1, + }).should.eql("abc"); + }); + + it("drains buffered text before generating another record", function () { + for (const highWaterMark of [1, 2, 3, 4, 7]) { + generateSync({ + columns: [() => "abc"], + length: 3, + fixed_size: true, + highWaterMark, + }).should.eql("abc\nabc\nabc"); + } + }); + + it("preserves records across streamed chunk boundaries", async function () { + const chunks = []; + for await (const chunk of generate({ + columns: [() => "abc"], + length: 3, + fixed_size: true, + highWaterMark: 1, + })) { + chunks.push(chunk); + } + Buffer.concat(chunks).toString().should.eql("abc\nabc\nabc"); + }); + + it("preserves the final suffix and eof in the callback API", function (next) { + generate( + { + columns: [() => "abc"], + length: 2, + fixed_size: true, + highWaterMark: 2, + row_delimiter: "|", + eof: true, + }, + (err, data) => { + if (err) return next(err); + data.toString().should.eql("abc|abc|"); + next(); + }, + ); + }); + it("with fixed_size", function (next) { let count = 0; const generator = generate({