javascript - What is causing "Uncaught Error: write after end" in my tests? -


i have following code:

var promise = require('bluebird'); promise.longstacktraces(); var path = require('path'); var fs = promise.promisifyall(require('fs-extra')); var clone = require('nodegit').clone.clone; var tar = require('tar-fs'); var zlib = require('zlib'); var gzip = zlib.creategzip(); var globasync = promise.promisify(require('glob'));  module.exports = archive;  function archive(pkg) {   var self = this;   var tmp_dir_name = '.tmp';   var code_dir_name = 'code';   var files_dir_name = 'files';   var output_dir_name = 'archives';   var coverall_docs_dir_name = 'coverall_documents';    // archive's name (no extension):   self.name = pkg.name;   self.recipient_name = pkg.recipient_name;   // path letter.tex:   self.tex_letter_path = path.resolve(pkg.files.letter);   // path resume.tex:   self.tex_resume_path = path.resolve(pkg.files.resume);   // path merged.pdf (letter.pdf + resume.pdf):   self.pdf_package_path = path.resolve(pkg.compiled_files.package);   // temp dir archive assembled:   self.tmp_path = path.resolve(tmp_dir_name, pkg.name);   // path final archive:   self.output_path = path.resolve(output_dir_name, self.name + '.tar.gz');   // copy files added archive:   self.files_path = path.resolve(tmp_dir_name, self.name, files_dir_name);   // tex files within archive:   self.coverall_docs_path = path.resolve(self.files_path, code_dir_name, coverall_docs_dir_name); }  archive.prototype.make = promise.method(function() {   var self = this;   return self._preparefilesdir()     .then(self._copyfiles.bind(self))     .then(self._writearchive.bind(self))     .then(self._deltmpdir.bind(self)); });  // ******************************** // * private functions // ********************************  archive.prototype._preparefilesdir = function() {   var self = this;   return fs.emptydirasync(self.tmp_path); };  archive.prototype._copyfiles = function() {   var self = this;   var sources = {     tex_letter_path: path.resolve(self.tex_letter_path, '..'),     tex_resume_path: path.resolve(self.tex_resume_path, '..'),     tex_letter_shared_path: path.resolve(self.tex_letter_path, '../../shared'),     pdf_package_path: self.pdf_package_path   };   var destinations = {     letter_path: path.resolve(self.coverall_docs_path, 'coverletters', self.recipient_name.tolowercase()),     resume_path: path.resolve(self.coverall_docs_path, 'resume'),     letter_shared_path: path.resolve(self.coverall_docs_path, 'coverletters/shared'),     pdf_package_path: path.resolve(self.files_path, 'pdf', self.recipient_name.tolowercase() + '.pdf'),     coverall_repo_path: path.resolve(self.files_path, 'code/coverall')   };   var filters = {     tex: function(filename) {       var contains_dot = /\./gm;       var hidden = /\/\./gm;       var cls_or_tex_file = /\.(cls|tex)$/gm;       var is_a_dir = !contains_dot.test(filename);       var is_not_hidden = (contains_dot.test(filename) && !hidden.test(filename));       var is_cls_or_tex = cls_or_tex_file.test(filename);       // doesn't contain dot or isn't hidden file or cls/tex file       var is_allowed = is_a_dir || is_not_hidden || is_cls_or_tex;       return is_allowed;     },     pdf: /[^\.].*\.pdf/   };    var copyletter = function() {     return fs.copyasync(sources.tex_letter_path, destinations.letter_path, { filter: filters.tex });   };   function copyshared() {     return fs.copyasync(sources.tex_letter_shared_path, destinations.letter_shared_path, { filter: filters.tex });   }   function copyresume() {     return fs.copyasync(sources.tex_resume_path, destinations.resume_path, { filter: filters.tex });   }   function copypdf() {     return fs.copyasync(sources.pdf_package_path, destinations.pdf_package_path, { filter: filters.pdf });   }   function copyjs() {     return clone('https://github.com/coaxial/coverall.git', destinations.coverall_repo_path);   }     return promise.all([       copyletter(),       copyshared(),       copyresume(),       copypdf(),       copyjs()   ]); };  archive.prototype._writearchive = function() {   var self = this;   var archive_dir_path = path.resolve(self.output_path, '..');   var tarpromise = function() {     return new promise(function(resolve, reject) {       tar.pack(self.files_path)         .pipe(gzip)         .pipe(fs.createwritestream(self.output_path))         .on('error', reject)         .on('finish', resolve);     });   };    return fs.ensuredirasync(archive_dir_path)     .then(tarpromise); };  archive.prototype._deltmpdir = function() {   var self = this;    return fs.removeasync(self.tmp_path); }; 

and testing with:

/*eslint-env mocha */ var chai = require('chai'); var chaiaspromised = require("chai-as-promised"); var expect = chai.expect; var promise = require('bluebird'); promise.longstacktraces(); var archive = require('../lib/archive'); var path = require('path'); var fs = promise.promisifyall(require('fs-extra')); var globasync = promise.promisify(require('glob')); var tar = require('tar-fs'); var zlib = promise.promisifyall(require('zlib')); var _ = require('lodash');  chai.use(chaiaspromised);  describe.only('archive', function() {   var pkg;    beforeeach(function() {     pkg = {       name: 'test_0790feebb1',       recipient_name: 'test',       files: {         letter: '../coverall_documents/coverletters/test/letter.tex',         resume: '../coverall_documents/resume/resume.tex'       },       compiled_files: {         package: '../coverall_documents/coverletters/test/test.pdf'       }     };   });    // after(function() {   //   return promise.all([   //       'archives/test*',   //       'test/.tmp'   //   ].map(function(glob_pattern) {   //     return globasync(glob_pattern)   //       .each(function(filename) {   //         // make every file writeable git packfiles can removed   //         return fs.chmodasync(filename, '755')   //           .then(function() { fs.removeasync(filename); });   //       })   //   }));   // });    describe('#make', function() {     it('creates archive', function() {       var modified_pkg = _.clonedeep(pkg);       modified_pkg.name = 'test_0000000001';       var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');       var test_archive = new archive(modified_pkg);        return test_archive.make()         .then(function() { return fs.statasync(archive_location); })         .then(function(file) { return expect(file).to.exist; })         .catch(function(e) { return expect(e).to.not.exist; });     });      it('creates gzip compressed archive', function() {       var modified_pkg = _.clonedeep(pkg);       modified_pkg.name = 'test_0000000002';       var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');       var test_archive = new archive(modified_pkg);        // inspired https://github.com/mafintosh/gunzip-maybe/blob/master/index.js#l6-l11       var isgzipped = function(data) {         var gzip_magic_bytes = [0x1f, 0x8b];         var deflate_compression_method = 0x08;         var buffer = data[1];          if (buffer[0] !== gzip_magic_bytes[0] && buffer[1] !== gzip_magic_bytes[1]) return false;         if (buffer[2] !== deflate_compression_method) return false;         return true;       };        return test_archive.make()         .then(function() { return fs.openasync(archive_location, 'r'); })         .then(function(fd) {            var buffer = new buffer(10);           var buffer_offset = 0;           var buffer_length = 10;           var file_position = 0;           return fs.readasync(fd, buffer, buffer_offset, buffer_length, file_position);         })       .then(function(data) { console.log('data', data); return data; })         .then(function(data) { return expect(isgzipped(data)).to.be.true; })     });      it('has correct directory structure', function() {       var modified_pkg = _.clonedeep(pkg);       modified_pkg.name = 'test_0000000003';       var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');       var test_archive = new archive(modified_pkg);       var tmp_extract_path = path.resolve('test/.tmp');        var tarpromise = function(archive_path) {         return new promise(function(resolve, reject) {           fs.createreadstream(archive_path)             .pipe(zlib.unzip())             .pipe(tar.extract(tmp_extract_path))             .on('error', reject)             .on('finish', resolve);         })       };        var verifydir = function() {         return promise.all([             'code',             'pdf',             'code/coverall',             'code/coverall_documents',             'code/coverall_documents/coverletters',             'code/coverall_documents/coverletters/test',             'code/coverall_documents/coverletters/shared',             'code/coverall_documents/resume',             'code/coverall_documents/coverletters'         ].map(function(subpath) {           return expect(fs.statasync(path.resolve(tmp_extract_path, subpath)))             .to.be.fulfilled;         }))       };        return test_archive.make()         .then(function() { return tarpromise(archive_location); })         .then(function() { return verifydir(); });     });      it('removes temporary dir', function() {       var modified_pkg = _.clonedeep(pkg);       modified_pkg.name = 'test_0000000004';       var archive_location = path.resolve('archives', modified_pkg.name + '.tar.gz');       var test_archive = new archive(modified_pkg);       var tmp_dir = path.resolve('.tmp');        return test_archive.make()         .then(function() { return expect(fs.statasync(tmp_dir)).to.be.rejected; });     });   }); }); 

which results in:

$ mocha test     archive     #make       ✓ creates archive (644ms)       1) creates gzip compressed archive       2) has correct directory structure       3) removes temporary dir     1 passing (2s)   3 failing    1) archive #make creates gzip compressed archive:      uncaught error: write after end       @ writeafterend (_stream_writable.js:167:12)       @ gzip.writable.write (_stream_writable.js:214:5)       @ ondata (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:574:20)       @ readableaddchunk (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:198:16)       @ readable.push (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:162:10)       @ pack._encode (node_modules/tar-fs/node_modules/tar-stream/pack.js:154:17)       @ pack.entry (node_modules/tar-fs/node_modules/tar-stream/pack.js:100:10)       @ onstat (node_modules/tar-fs/index.js:108:19)       @ node_modules/tar-fs/index.js:40:9       @ fsreqwrap.oncomplete (fs.js:95:15)    2) archive #make has correct directory structure:      assertionerror: expected false true       @ context.<anonymous> (test/archive_spec.js:96:10)    3) archive #make removes temporary dir:      uncaught error: write after end       @ writeafterend (_stream_writable.js:167:12)       @ gzip.writable.write (_stream_writable.js:214:5)       @ ondata (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:574:20)       @ readableaddchunk (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:198:16)       @ readable.push (node_modules/tar-fs/node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js:162:10)       @ pack._encode (node_modules/tar-fs/node_modules/tar-stream/pack.js:154:17)       @ pack.entry (node_modules/tar-fs/node_modules/tar-stream/pack.js:100:10)       @ onstat (node_modules/tar-fs/index.js:108:19)       @ node_modules/tar-fs/index.js:40:9       @ fsreqwrap.oncomplete (fs.js:95:15) 

i suspected race condition commented out after block see if make difference doesn't.

i not understand uncaught error: write after end nor why stacktrace unusable, though using promise.longstacktraces(). causing error?

my tests overly complicated doing , repeating code several times when instantiating different test_archive objects. how refactor them?

you're trying re-use same gzip instance, won't work. explains why first test works fine.

so move var gzip = zlib.creategzip(); line right inside archive.prototype._writearchive function.


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -