CoolFace
Apppublic

strong-tie/inbound-calls

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
flush.test.js420 linesDownload Raw Back to test
1'use strict'2 3const fs = require('fs')4const path = require('path')5const SonicBoom = require('../')6const { file, runTests } = require('./helper')7const proxyquire = require('proxyquire')8 9runTests(buildTests)10 11function buildTests (test, sync) {12  // Reset the unmask for testing13  process.umask(0o000)14 15  test('append', (t) => {16    t.plan(4)17 18    const dest = file()19    fs.writeFileSync(dest, 'hello world\n')20    const stream = new SonicBoom({ dest, append: false, sync })21 22    stream.on('ready', () => {23      t.pass('ready emitted')24    })25 26    t.ok(stream.write('something else\n'))27 28    stream.flush()29 30    stream.on('drain', () => {31      fs.readFile(dest, 'utf8', (err, data) => {32        t.error(err)33        t.equal(data, 'something else\n')34        stream.end()35      })36    })37  })38 39  test('mkdir', (t) => {40    t.plan(4)41 42    const dest = path.join(file(), 'out.log')43    const stream = new SonicBoom({ dest, mkdir: true, sync })44 45    stream.on('ready', () => {46      t.pass('ready emitted')47    })48 49    t.ok(stream.write('hello world\n'))50 51    stream.flush()52 53    stream.on('drain', () => {54      fs.readFile(dest, 'utf8', (err, data) => {55        t.error(err)56        t.equal(data, 'hello world\n')57        stream.end()58      })59    })60  })61 62  test('flush', (t) => {63    t.plan(5)64 65    const dest = file()66    const fd = fs.openSync(dest, 'w')67    const stream = new SonicBoom({ fd, minLength: 4096, sync })68 69    stream.on('ready', () => {70      t.pass('ready emitted')71    })72 73    t.ok(stream.write('hello world\n'))74    t.ok(stream.write('something else\n'))75 76    stream.flush()77 78    stream.on('drain', () => {79      fs.readFile(dest, 'utf8', (err, data) => {80        t.error(err)81        t.equal(data, 'hello world\nsomething else\n')82        stream.end()83      })84    })85  })86 87  test('flush with no data', (t) => {88    t.plan(2)89 90    const dest = file()91    const fd = fs.openSync(dest, 'w')92    const stream = new SonicBoom({ fd, minLength: 4096, sync })93 94    stream.on('ready', () => {95      t.pass('ready emitted')96    })97 98    stream.flush()99 100    stream.on('drain', () => {101      t.pass('drain emitted')102    })103  })104 105  test('call flush cb after flushed', (t) => {106    t.plan(4)107 108    const dest = file()109    const fd = fs.openSync(dest, 'w')110    const stream = new SonicBoom({ fd, minLength: 4096, sync })111 112    stream.on('ready', () => {113      t.pass('ready emitted')114    })115 116    t.ok(stream.write('hello world\n'))117    t.ok(stream.write('something else\n'))118 119    stream.flush((err) => {120      if (err) t.fail(err)121      else t.pass('flush cb called')122    })123  })124 125  test('only call fsyncSync and not fsync when fsync: true', (t) => {126    t.plan(6)127 128    const fakeFs = Object.create(fs)129    const SonicBoom = proxyquire('../', {130      fs: fakeFs131    })132 133    const dest = file()134    const fd = fs.openSync(dest, 'w')135    const stream = new SonicBoom({136      fd,137      sync,138      fsync: true,139      minLength: 4096140    })141 142    stream.on('ready', () => {143      t.pass('ready emitted')144    })145 146    fakeFs.fsync = function (fd, cb) {147      t.fail('fake fs.fsync called while should not')148      cb()149    }150    fakeFs.fsyncSync = function (fd) {151      t.pass('fake fsyncSync called')152    }153 154    function successOnAsyncOrSyncFn (isSync, originalFn) {155      return function (...args) {156        t.pass(`fake fs.${originalFn.name} called`)157        fakeFs[originalFn.name] = originalFn158        return fakeFs[originalFn.name](...args)159      }160    }161 162    if (sync) {163      fakeFs.writeSync = successOnAsyncOrSyncFn(true, fs.writeSync)164    } else {165      fakeFs.write = successOnAsyncOrSyncFn(false, fs.write)166    }167 168    t.ok(stream.write('hello world\n'))169    stream.flush((err) => {170      if (err) t.fail(err)171      else t.pass('flush cb called')172 173      process.nextTick(() => {174        // to make sure fsync is not called as well175        t.pass('nextTick after flush called')176      })177    })178  })179 180  test('call flush cb with error when fsync failed', (t) => {181    t.plan(5)182 183    const fakeFs = Object.create(fs)184    const SonicBoom = proxyquire('../', {185      fs: fakeFs186    })187 188    const dest = file()189    const fd = fs.openSync(dest, 'w')190    const stream = new SonicBoom({191      fd,192      sync,193      minLength: 4096194    })195 196    stream.on('ready', () => {197      t.pass('ready emitted')198    })199 200    const err = new Error('other')201    err.code = 'other'202 203    function onFsyncOnFsyncSync (isSync, originalFn) {204      return function (...args) {205        Error.captureStackTrace(err)206        t.pass(`fake fs.${originalFn.name} called`)207        fakeFs[originalFn.name] = originalFn208        const cb = args[args.length - 1]209 210        cb(err)211      }212    }213 214    // only one is called depends on sync215    fakeFs.fsync = onFsyncOnFsyncSync(false, fs.fsync)216 217    function successOnAsyncOrSyncFn (isSync, originalFn) {218      return function (...args) {219        t.pass(`fake fs.${originalFn.name} called`)220        fakeFs[originalFn.name] = originalFn221        return fakeFs[originalFn.name](...args)222      }223    }224 225    if (sync) {226      fakeFs.writeSync = successOnAsyncOrSyncFn(true, fs.writeSync)227    } else {228      fakeFs.write = successOnAsyncOrSyncFn(false, fs.write)229    }230 231    t.ok(stream.write('hello world\n'))232    stream.flush((err) => {233      if (err) t.equal(err.code, 'other')234      else t.fail('flush cb called without an error')235    })236  })237 238  test('call flush cb even when have no data', (t) => {239    t.plan(2)240 241    const dest = file()242    const fd = fs.openSync(dest, 'w')243    const stream = new SonicBoom({ fd, minLength: 4096, sync })244 245    stream.on('ready', () => {246      t.pass('ready emitted')247 248      stream.flush((err) => {249        if (err) t.fail(err)250        else t.pass('flush cb called')251      })252    })253  })254 255  test('call flush cb even when minLength is 0', (t) => {256    t.plan(1)257 258    const dest = file()259    const fd = fs.openSync(dest, 'w')260    const stream = new SonicBoom({ fd, minLength: 0, sync })261 262    stream.flush((err) => {263      if (err) t.fail(err)264      else t.pass('flush cb called')265    })266  })267 268  test('call flush cb with an error when trying to flush destroyed stream', (t) => {269    t.plan(1)270 271    const dest = file()272    const fd = fs.openSync(dest, 'w')273    const stream = new SonicBoom({ fd, minLength: 4096, sync })274    stream.destroy()275 276    stream.flush((err) => {277      if (err) t.pass(err)278      else t.fail('flush cb called without an error')279    })280  })281 282  test('call flush cb with an error when failed to flush', (t) => {283    t.plan(5)284 285    const fakeFs = Object.create(fs)286    const SonicBoom = proxyquire('../', {287      fs: fakeFs288    })289 290    const dest = file()291    const fd = fs.openSync(dest, 'w')292    const stream = new SonicBoom({293      fd,294      sync,295      minLength: 4096296    })297 298    stream.on('ready', () => {299      t.pass('ready emitted')300    })301 302    const err = new Error('other')303    err.code = 'other'304 305    function onWriteOrWriteSync (isSync, originalFn) {306      return function (...args) {307        Error.captureStackTrace(err)308        t.pass(`fake fs.${originalFn.name} called`)309        fakeFs[originalFn.name] = originalFn310 311        if (isSync) throw err312        const cb = args[args.length - 1]313 314        cb(err)315      }316    }317 318    // only one is called depends on sync319    fakeFs.write = onWriteOrWriteSync(false, fs.write)320    fakeFs.writeSync = onWriteOrWriteSync(true, fs.writeSync)321 322    t.ok(stream.write('hello world\n'))323    stream.flush((err) => {324      if (err) t.equal(err.code, 'other')325      else t.fail('flush cb called without an error')326    })327 328    stream.end()329 330    stream.on('close', () => {331      t.pass('close emitted')332    })333  })334 335  test('call flush cb when finish writing when currently in the middle', (t) => {336    t.plan(4)337 338    const fakeFs = Object.create(fs)339    const SonicBoom = proxyquire('../', {340      fs: fakeFs341    })342 343    const dest = file()344    const fd = fs.openSync(dest, 'w')345    const stream = new SonicBoom({346      fd,347      sync,348 349      // to trigger write without calling flush350      minLength: 1351    })352 353    stream.on('ready', () => {354      t.pass('ready emitted')355    })356 357    function onWriteOrWriteSync (originalFn) {358      return function (...args) {359        stream.flush((err) => {360          if (err) t.fail(err)361          else t.pass('flush cb called')362        })363 364        t.pass(`fake fs.${originalFn.name} called`)365        fakeFs[originalFn.name] = originalFn366        return originalFn(...args)367      }368    }369 370    // only one is called depends on sync371    fakeFs.write = onWriteOrWriteSync(fs.write)372    fakeFs.writeSync = onWriteOrWriteSync(fs.writeSync)373 374    t.ok(stream.write('hello world\n'))375  })376 377  test('call flush cb when writing and trying to flush before ready (on async)', (t) => {378    t.plan(4)379 380    const fakeFs = Object.create(fs)381    const SonicBoom = proxyquire('../', {382      fs: fakeFs383    })384 385    fakeFs.open = fsOpen386 387    const dest = file()388    const stream = new SonicBoom({389      fd: dest,390      // only async as sync is part of the constructor so the user will not be able to call write/flush391      // before ready392      sync: false,393 394      // to not trigger write without calling flush395      minLength: 4096396    })397 398    stream.on('ready', () => {399      t.pass('ready emitted')400    })401 402    function fsOpen (...args) {403      process.nextTick(() => {404        // try writing and flushing before ready and in the middle of opening405        t.pass('fake fs.open called')406        t.ok(stream.write('hello world\n'))407 408        // calling flush409        stream.flush((err) => {410          if (err) t.fail(err)411          else t.pass('flush cb called')412        })413 414        fakeFs.open = fs.open415        fs.open(...args)416      })417    }418  })419}420