DateRollingFileStream-test.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. "use strict";
  2. var should = require('should')
  3. , fs = require('fs')
  4. , zlib = require('zlib')
  5. , util = require('util')
  6. , async = require('async')
  7. , format = require('date-format')
  8. , streams = require('readable-stream')
  9. , DateRollingFileStream
  10. , testTime = new Date(2012, 8, 12, 10, 37, 11);
  11. DateRollingFileStream = require('../lib').DateRollingFileStream;
  12. function remove(filename, cb) {
  13. fs.unlink(filename, function () {
  14. cb();
  15. });
  16. }
  17. function now() {
  18. return testTime.getTime();
  19. }
  20. describe('DateRollingFileStream', function () {
  21. describe('arguments', function () {
  22. var stream;
  23. before(function (done) {
  24. stream = new DateRollingFileStream(
  25. __dirname + '/test-date-rolling-file-stream-1',
  26. 'yyyy-mm-dd.hh'
  27. );
  28. done();
  29. });
  30. after(function (done) {
  31. remove(__dirname + '/test-date-rolling-file-stream-1', done);
  32. });
  33. it('should take a filename and a pattern and return a WritableStream', function (done) {
  34. stream.filename.should.eql(__dirname + '/test-date-rolling-file-stream-1');
  35. stream.pattern.should.eql('yyyy-mm-dd.hh');
  36. stream.should.be.instanceOf(streams.Writable);
  37. done();
  38. });
  39. it('with default settings for the underlying stream', function (done) {
  40. stream.theStream.mode.should.eql(420);
  41. stream.theStream.flags.should.eql('a');
  42. //encoding is not available on the underlying stream
  43. //assert.equal(stream.encoding, 'utf8');
  44. done();
  45. });
  46. });
  47. describe('default arguments', function () {
  48. var stream;
  49. before(function(done) {
  50. stream = new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-2');
  51. done();
  52. });
  53. after(function (done) {
  54. remove(__dirname + '/test-date-rolling-file-stream-2', done);
  55. });
  56. it('should have pattern of .yyyy-MM-dd', function (done) {
  57. stream.pattern.should.eql('.yyyy-MM-dd');
  58. done();
  59. });
  60. });
  61. describe('with stream arguments', function () {
  62. var stream;
  63. before(function(done) {
  64. stream = new DateRollingFileStream(
  65. __dirname + '/test-date-rolling-file-stream-3',
  66. 'yyyy-MM-dd',
  67. {mode: parseInt('0666', 8)}
  68. );
  69. done();
  70. });
  71. after(function (done) {
  72. remove(__dirname + '/test-date-rolling-file-stream-3', done);
  73. });
  74. it('should pass them to the underlying stream', function (done) {
  75. stream.theStream.mode.should.eql(parseInt('0666', 8));
  76. done();
  77. });
  78. });
  79. describe('with stream arguments but no pattern', function () {
  80. var stream;
  81. before(function (done) {
  82. stream = new DateRollingFileStream(
  83. __dirname + '/test-date-rolling-file-stream-4',
  84. {mode: parseInt('0666', 8)}
  85. );
  86. done();
  87. });
  88. after(function (done) {
  89. remove(__dirname + '/test-date-rolling-file-stream-4', done);
  90. });
  91. it('should pass them to the underlying stream', function (done) {
  92. stream.theStream.mode.should.eql(parseInt('0666', 8));
  93. done();
  94. });
  95. it('should use default pattern', function (done) {
  96. stream.pattern.should.eql('.yyyy-MM-dd');
  97. done();
  98. });
  99. });
  100. describe('with a pattern of .yyyy-MM-dd', function () {
  101. var stream;
  102. before(function (done) {
  103. stream = new DateRollingFileStream(
  104. __dirname + '/test-date-rolling-file-stream-5', '.yyyy-MM-dd',
  105. null,
  106. now
  107. );
  108. stream.write("First message\n", 'utf8', done);
  109. });
  110. after(function (done) {
  111. remove(__dirname + '/test-date-rolling-file-stream-5', done);
  112. });
  113. it('should create a file with the base name', function (done) {
  114. fs.readFile(__dirname + '/test-date-rolling-file-stream-5', 'utf8', function (err, contents) {
  115. contents.should.eql("First message\n");
  116. done(err);
  117. });
  118. });
  119. describe('when the day changes', function () {
  120. before(function (done) {
  121. testTime = new Date(2012, 8, 13, 0, 10, 12);
  122. stream.write("Second message\n", 'utf8', done);
  123. });
  124. after(function (done) {
  125. remove(__dirname + '/test-date-rolling-file-stream-5.2012-09-12', done);
  126. });
  127. describe('the number of files', function () {
  128. var files = [];
  129. before(function (done) {
  130. fs.readdir(__dirname, function (err, list) {
  131. files = list;
  132. done(err);
  133. });
  134. });
  135. it('should be two', function (done) {
  136. files.filter(
  137. function (file) {
  138. return file.indexOf('test-date-rolling-file-stream-5') > -1;
  139. }
  140. ).should.have.length(2);
  141. done();
  142. });
  143. });
  144. describe('the file without a date', function () {
  145. it('should contain the second message', function (done) {
  146. fs.readFile(
  147. __dirname + '/test-date-rolling-file-stream-5', 'utf8',
  148. function (err, contents) {
  149. contents.should.eql("Second message\n");
  150. done(err);
  151. }
  152. );
  153. });
  154. });
  155. describe('the file with the date', function () {
  156. it('should contain the first message', function (done) {
  157. fs.readFile(
  158. __dirname + '/test-date-rolling-file-stream-5.2012-09-12', 'utf8',
  159. function (err, contents) {
  160. contents.should.eql("First message\n");
  161. done(err);
  162. }
  163. );
  164. });
  165. });
  166. });
  167. });
  168. describe('with alwaysIncludePattern', function () {
  169. var stream;
  170. before(function (done) {
  171. testTime = new Date(2012, 8, 12, 0, 10, 12);
  172. remove(
  173. __dirname + '/test-date-rolling-file-stream-pattern.2012-09-12',
  174. function () {
  175. stream = new DateRollingFileStream(
  176. __dirname + '/test-date-rolling-file-stream-pattern',
  177. '.yyyy-MM-dd',
  178. {alwaysIncludePattern: true},
  179. now
  180. );
  181. setTimeout(function() {
  182. stream.write("First message\n", 'utf8', done);
  183. }, 50);
  184. }
  185. );
  186. });
  187. after(function (done) {
  188. remove(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-12', done);
  189. });
  190. it('should create a file with the pattern set', function (done) {
  191. fs.readFile(
  192. __dirname + '/test-date-rolling-file-stream-pattern.2012-09-12', 'utf8',
  193. function (err, contents) {
  194. contents.should.eql("First message\n");
  195. done(err);
  196. }
  197. );
  198. });
  199. describe('when the day changes', function () {
  200. before(function (done) {
  201. testTime = new Date(2012, 8, 13, 0, 10, 12);
  202. stream.write("Second message\n", 'utf8', done);
  203. });
  204. after(function (done) {
  205. remove(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-13', done);
  206. });
  207. describe('the number of files', function () {
  208. it('should be two', function (done) {
  209. fs.readdir(__dirname, function (err, files) {
  210. files.filter(
  211. function (file) {
  212. return file.indexOf('test-date-rolling-file-stream-pattern') > -1;
  213. }
  214. ).should.have.length(2);
  215. done(err);
  216. });
  217. });
  218. });
  219. describe('the file with the later date', function () {
  220. it('should contain the second message', function (done) {
  221. fs.readFile(
  222. __dirname + '/test-date-rolling-file-stream-pattern.2012-09-13', 'utf8',
  223. function (err, contents) {
  224. contents.should.eql("Second message\n");
  225. done(err);
  226. }
  227. );
  228. });
  229. });
  230. describe('the file with the date', function () {
  231. it('should contain the first message', function (done) {
  232. fs.readFile(
  233. __dirname + '/test-date-rolling-file-stream-pattern.2012-09-12', 'utf8',
  234. function (err, contents) {
  235. contents.should.eql("First message\n");
  236. done(err);
  237. }
  238. );
  239. });
  240. });
  241. });
  242. });
  243. describe('with compress option', function () {
  244. var stream;
  245. before(function (done) {
  246. testTime = new Date(2012, 8, 12, 0, 10, 12);
  247. stream = new DateRollingFileStream(
  248. __dirname + '/compressed.log',
  249. '.yyyy-MM-dd',
  250. {compress: true},
  251. now
  252. );
  253. stream.write("First message\n", 'utf8', done);
  254. });
  255. describe('when the day changes', function () {
  256. before(function (done) {
  257. testTime = new Date(2012, 8, 13, 0, 10, 12);
  258. stream.write("Second message\n", 'utf8', done);
  259. });
  260. it('should be two files, one compressed', function (done) {
  261. fs.readdir(__dirname, function (err, files) {
  262. var logFiles = files.filter(
  263. function (file) {
  264. return file.indexOf('compressed.log') > -1;
  265. }
  266. );
  267. logFiles.should.have.length(2);
  268. zlib.gunzip(
  269. fs.readFileSync(__dirname + '/compressed.log.2012-09-12.gz'),
  270. function (err, contents) {
  271. contents.toString('utf8').should.eql('First message\n');
  272. fs.readFileSync(__dirname + '/compressed.log', 'utf8').should.eql('Second message\n');
  273. done(err);
  274. }
  275. );
  276. });
  277. });
  278. });
  279. after(function (done) {
  280. remove(
  281. __dirname + '/compressed.log',
  282. function () {
  283. remove(__dirname + '/compressed.log.2012-09-12.gz', done);
  284. }
  285. );
  286. });
  287. });
  288. describe('with keepFileExt option', function () {
  289. var stream;
  290. before(function (done) {
  291. testTime = new Date(2012, 8, 12, 0, 10, 12);
  292. stream = new DateRollingFileStream(
  293. __dirname + '/keepFileExt.log',
  294. '.yyyy-MM-dd',
  295. {keepFileExt: true},
  296. now
  297. );
  298. stream.write("First message\n", 'utf8', done);
  299. });
  300. describe('when the day changes', function () {
  301. before(function (done) {
  302. testTime = new Date(2012, 8, 13, 0, 10, 12);
  303. stream.write("Second message\n", 'utf8', done);
  304. });
  305. it('should be two files', function (done) {
  306. fs.readdir(__dirname, function (err, files) {
  307. var logFiles = files.filter(
  308. function (file) {
  309. return file.indexOf('keepFileExt') > -1;
  310. }
  311. );
  312. logFiles.should.have.length(2);
  313. fs.readFileSync(__dirname + '/keepFileExt.2012-09-12.log', 'utf8')
  314. .should.eql('First message\n');
  315. fs.readFileSync(__dirname + '/keepFileExt.log', 'utf8')
  316. .should.eql('Second message\n');
  317. done(err);
  318. });
  319. });
  320. });
  321. after(function (done) {
  322. remove(
  323. __dirname + '/keepFileExt.log',
  324. function () {
  325. remove(__dirname + '/keepFileExt.2012-09-12.log', done);
  326. }
  327. );
  328. });
  329. });
  330. describe('with compress option and keepFileExt option', function () {
  331. var stream;
  332. before(function (done) {
  333. testTime = new Date(2012, 8, 12, 0, 10, 12);
  334. stream = new DateRollingFileStream(
  335. __dirname + '/compressedAndKeepExt.log',
  336. '.yyyy-MM-dd',
  337. {compress: true, keepFileExt: true},
  338. now
  339. );
  340. stream.write("First message\n", 'utf8', done);
  341. });
  342. describe('when the day changes', function () {
  343. before(function (done) {
  344. testTime = new Date(2012, 8, 13, 0, 10, 12);
  345. stream.write("Second message\n", 'utf8', done);
  346. });
  347. it('should be two files, one compressed', function (done) {
  348. fs.readdir(__dirname, function (err, files) {
  349. var logFiles = files.filter(
  350. function (file) {
  351. return file.indexOf('compressedAndKeepExt') > -1;
  352. }
  353. );
  354. logFiles.should.have.length(2);
  355. zlib.gunzip(
  356. fs.readFileSync(__dirname + '/compressedAndKeepExt.2012-09-12.log.gz'),
  357. function (err, contents) {
  358. contents.toString('utf8').should.eql('First message\n');
  359. fs.readFileSync(__dirname + '/compressedAndKeepExt.log', 'utf8')
  360. .should.eql('Second message\n');
  361. done(err);
  362. }
  363. );
  364. });
  365. });
  366. });
  367. after(function (done) {
  368. remove(
  369. __dirname + '/compressedAndKeepExt.log',
  370. function () {
  371. remove(__dirname + '/compressedAndKeepExt.log.2012-09-12.gz', done);
  372. }
  373. );
  374. });
  375. });
  376. describe('with daysToKeep option', function () {
  377. var stream;
  378. var daysToKeep = 4;
  379. var numOriginalLogs = 10;
  380. before(function (done) {
  381. var day = 0;
  382. var streams = [];
  383. async.whilst(
  384. function () {
  385. return day < numOriginalLogs;
  386. },
  387. function (nextCallback) {
  388. testTime = new Date(2012, 8, 20 - day, 0, 10, 12);
  389. var currentStream = new DateRollingFileStream(
  390. __dirname + '/daysToKeep.log',
  391. '.yyyy-MM-dd',
  392. {
  393. alwaysIncludePattern: true,
  394. daysToKeep: daysToKeep
  395. },
  396. now
  397. );
  398. async.waterfall([
  399. function (callback) {
  400. currentStream.write(util.format("Message on day %d\n", day), 'utf8', callback);
  401. },
  402. function (callback) {
  403. fs.utimes(currentStream.filename, testTime, testTime, callback);
  404. }
  405. ],
  406. function (err) {
  407. day++;
  408. streams.push(currentStream);
  409. nextCallback(err);
  410. });
  411. },
  412. function (err, n) {
  413. stream = streams[0];
  414. done(err);
  415. });
  416. describe('when the day changes', function () {
  417. before(function (done) {
  418. testTime = new Date(2012, 8, 21, 0, 10, 12);
  419. stream.write("Second message\n", 'utf8', done);
  420. });
  421. it('should be daysToKeep + 1 files left from numOriginalLogs', function (done) {
  422. fs.readdir(__dirname, function (err, files) {
  423. var logFiles = files.filter(
  424. function (file) {
  425. return file.indexOf('daysToKeep.log') > -1;
  426. }
  427. );
  428. logFiles.should.have.length(daysToKeep + 1);
  429. done(err);
  430. });
  431. });
  432. });
  433. after(function (done) {
  434. fs.readdir(__dirname, function (err, files) {
  435. var logFiles = files.filter(
  436. function (file) {
  437. return file.indexOf('daysToKeep.log') > -1;
  438. }
  439. );
  440. async.each(logFiles, function (logFile, nextCallback) {
  441. remove(__dirname + "/" + logFile, nextCallback);
  442. },
  443. function (err) {
  444. done(err);
  445. });
  446. });
  447. });
  448. });
  449. });
  450. describe('with daysToKeep and compress options', function () {
  451. var stream;
  452. var daysToKeep = 4;
  453. var numOriginalLogs = 10;
  454. before(function (done) {
  455. var day = 0;
  456. var streams = [];
  457. async.whilst(
  458. function () {
  459. return day < numOriginalLogs;
  460. },
  461. function (nextCallback) {
  462. testTime = new Date(2012, 8, 20 - day, 0, 10, 12);
  463. var currentStream = new DateRollingFileStream(
  464. __dirname + '/compressedDaysToKeep.log',
  465. '.yyyy-MM-dd',
  466. {
  467. alwaysIncludePattern: true,
  468. compress: true,
  469. daysToKeep: daysToKeep
  470. },
  471. now
  472. );
  473. async.waterfall([
  474. function (callback) {
  475. currentStream.write(util.format("Message on day %d\n", day), 'utf8', callback);
  476. },
  477. function (callback) {
  478. currentStream.compress(currentStream.filename, callback);
  479. },
  480. function (callback) {
  481. fs.utimes(currentStream.filename + ".gz", testTime, testTime, callback);
  482. }
  483. ],
  484. function (err) {
  485. day++;
  486. streams.push(currentStream);
  487. nextCallback(err);
  488. });
  489. },
  490. function (err, n) {
  491. // Uncompress the most recent stream which will be the one we roll over
  492. // for testing
  493. stream = streams[0];
  494. var compressedFilename = stream.filename + '.gz';
  495. var gzip = zlib.createGzip();
  496. var inp = fs.createReadStream(compressedFilename);
  497. var out = fs.createWriteStream(stream.filename);
  498. inp.pipe(gzip).pipe(out);
  499. out.on('finish', function (err) {
  500. fs.unlink(compressedFilename, done);
  501. });
  502. });
  503. });
  504. describe('when the day changes', function () {
  505. before(function (done) {
  506. testTime = new Date(2012, 8, 21, 0, 10, 12);
  507. stream.write("New file message\n", 'utf8', done);
  508. });
  509. it('should be 4 files left from original 3', function (done) {
  510. fs.readdir(__dirname, function (err, files) {
  511. var logFiles = files.filter(
  512. function (file) {
  513. return file.indexOf('compressedDaysToKeep.log') > -1;
  514. }
  515. );
  516. logFiles.should.have.length(daysToKeep + 1);
  517. done(err);
  518. });
  519. });
  520. });
  521. after(function (done) {
  522. fs.readdir(__dirname, function (err, files) {
  523. var logFiles = files.filter(
  524. function (file) {
  525. return file.indexOf('compressedDaysToKeep.log') > -1;
  526. }
  527. );
  528. async.each(logFiles, function (logFile, nextCallback) {
  529. remove(__dirname + "/" + logFile, nextCallback);
  530. },
  531. function (err) {
  532. done(err);
  533. });
  534. });
  535. });
  536. });
  537. });