strong-tie/inbound-calls
0
1'use strict'2 3const { test } = require('tap')4const fs = require('fs')5const proxyquire = require('proxyquire')6const SonicBoom = require('../')7const { file } = require('./helper')8 9test('write buffers that are not totally written with sync mode', (t) => {10 t.plan(9)11 12 const fakeFs = Object.create(fs)13 fakeFs.writeSync = function (fd, buf, enc) {14 t.pass('fake fs.write called')15 fakeFs.writeSync = (fd, buf, enc) => {16 t.pass('calling real fs.writeSync, ' + buf)17 return fs.writeSync(fd, buf, enc)18 }19 return 020 }21 const SonicBoom = proxyquire('../', {22 fs: fakeFs23 })24 25 const dest = file()26 const fd = fs.openSync(dest, 'w')27 const stream = new SonicBoom({ fd, minLength: 0, sync: true })28 29 stream.on('ready', () => {30 t.pass('ready emitted')31 })32 33 t.ok(stream.write('hello world\n'))34 t.ok(stream.write('something else\n'))35 36 stream.end()37 38 stream.on('finish', () => {39 fs.readFile(dest, 'utf8', (err, data) => {40 t.error(err)41 t.equal(data, 'hello world\nsomething else\n')42 })43 })44 stream.on('close', () => {45 t.pass('close emitted')46 })47})48 49test('write buffers that are not totally written with flush sync', (t) => {50 t.plan(7)51 52 const fakeFs = Object.create(fs)53 fakeFs.writeSync = function (fd, buf, enc) {54 t.pass('fake fs.write called')55 fakeFs.writeSync = fs.writeSync56 return 057 }58 const SonicBoom = proxyquire('../', {59 fs: fakeFs60 })61 62 const dest = file()63 const fd = fs.openSync(dest, 'w')64 const stream = new SonicBoom({ fd, minLength: 100, sync: false })65 66 stream.on('ready', () => {67 t.pass('ready emitted')68 })69 70 t.ok(stream.write('hello world\n'))71 t.ok(stream.write('something else\n'))72 73 stream.flushSync()74 75 stream.on('write', (n) => {76 if (n === 0) {77 t.fail('throwing to avoid infinite loop')78 throw Error('shouldn\'t call write handler after flushing with n === 0')79 }80 })81 82 stream.end()83 84 stream.on('finish', () => {85 fs.readFile(dest, 'utf8', (err, data) => {86 t.error(err)87 t.equal(data, 'hello world\nsomething else\n')88 })89 })90 stream.on('close', () => {91 t.pass('close emitted')92 })93})94 95test('sync writing is fully sync', (t) => {96 t.plan(6)97 98 const fakeFs = Object.create(fs)99 fakeFs.writeSync = function (fd, buf, enc, cb) {100 t.pass('fake fs.write called')101 return fs.writeSync(fd, buf, enc)102 }103 const SonicBoom = proxyquire('../', {104 fs: fakeFs105 })106 107 const dest = file()108 const fd = fs.openSync(dest, 'w')109 const stream = new SonicBoom({ fd, minLength: 0, sync: true })110 t.ok(stream.write('hello world\n'))111 t.ok(stream.write('something else\n'))112 113 // 'drain' will be only emitted once,114 // the number of assertions at the top check this.115 stream.on('drain', () => {116 t.pass('drain emitted')117 })118 119 const data = fs.readFileSync(dest, 'utf8')120 t.equal(data, 'hello world\nsomething else\n')121})122 123test('write enormously large buffers sync', (t) => {124 t.plan(3)125 126 const dest = file()127 const fd = fs.openSync(dest, 'w')128 const stream = new SonicBoom({ fd, minLength: 0, sync: true })129 130 const buf = Buffer.alloc(1024).fill('x').toString() // 1 MB131 let length = 0132 133 for (let i = 0; i < 1024 * 512; i++) {134 length += buf.length135 stream.write(buf)136 }137 138 stream.end()139 140 stream.on('finish', () => {141 fs.stat(dest, (err, stat) => {142 t.error(err)143 t.equal(stat.size, length)144 })145 })146 stream.on('close', () => {147 t.pass('close emitted')148 })149})150 151test('write enormously large buffers sync with utf8 multi-byte split', (t) => {152 t.plan(4)153 154 const dest = file()155 const fd = fs.openSync(dest, 'w')156 const stream = new SonicBoom({ fd, minLength: 0, sync: true })157 158 let buf = Buffer.alloc((1024 * 16) - 2).fill('x') // 16MB - 3B159 const length = buf.length + 4160 buf = buf.toString() + '๐ฒ' // 16 MB + 1B161 162 stream.write(buf)163 164 stream.end()165 166 stream.on('finish', () => {167 fs.stat(dest, (err, stat) => {168 t.error(err)169 t.equal(stat.size, length)170 const char = Buffer.alloc(4)171 const fd = fs.openSync(dest, 'r')172 fs.readSync(fd, char, 0, 4, length - 4)173 t.equal(char.toString(), '๐ฒ')174 })175 })176 stream.on('close', () => {177 t.pass('close emitted')178 })179})180 181// for context see this issue https://github.com/pinojs/pino/issues/871182test('file specified by dest path available immediately when options.sync is true', (t) => {183 t.plan(3)184 const dest = file()185 const stream = new SonicBoom({ dest, sync: true })186 t.ok(stream.write('hello world\n'))187 t.ok(stream.write('something else\n'))188 stream.flushSync()189 t.pass('file opened and written to without error')190})191 192test('sync error handling', (t) => {193 t.plan(1)194 try {195 /* eslint no-new: off */196 new SonicBoom({ dest: '/path/to/nowwhere', sync: true })197 t.fail('must throw synchronously')198 } catch (err) {199 t.pass('an error happened')200 }201})202 203for (const fd of [1, 2]) {204 test(`fd ${fd}`, (t) => {205 t.plan(1)206 207 const fakeFs = Object.create(fs)208 const SonicBoom = proxyquire('../', {209 fs: fakeFs210 })211 212 const stream = new SonicBoom({ fd })213 214 fakeFs.close = function (fd, cb) {215 t.fail(`should not close fd ${fd}`)216 }217 218 stream.end()219 220 stream.on('close', () => {221 t.pass('close emitted')222 })223 })224}225 226test('._len must always be equal or greater than 0', (t) => {227 t.plan(3)228 229 const dest = file()230 const fd = fs.openSync(dest, 'w')231 const stream = new SonicBoom({ fd, sync: true })232 233 t.ok(stream.write('hello world ๐\n'))234 t.ok(stream.write('another line ๐\n'))235 236 t.equal(stream._len, 0)237 238 stream.end()239})240 241test('._len must always be equal or greater than 0', (t) => {242 const n = 20243 t.plan(n + 3)244 245 const dest = file()246 const fd = fs.openSync(dest, 'w')247 const stream = new SonicBoom({ fd, sync: true, minLength: 20 })248 249 let str = ''250 for (let i = 0; i < 20; i++) {251 t.ok(stream.write('๐'))252 str += '๐'253 }254 255 t.equal(stream._len, 0)256 257 fs.readFile(dest, 'utf8', (err, data) => {258 t.error(err)259 t.equal(data, str)260 })261})262 