fs.tap.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. 'use strict';
  2. var createNamespace = require('../context.js').createNamespace
  3. , fs = require('fs')
  4. , path = require('path')
  5. , exec = require('child_process').exec
  6. , tap = require('tap')
  7. , test = tap.test
  8. ;
  9. // CONSTANTS
  10. var FILENAME = '__testfile'
  11. , DIRNAME = '__TESTDIR'
  12. , LINKNAME = '__testlink'
  13. , HARDLINKNAME = '__testhardlink'
  14. ;
  15. function createFile(assert) {
  16. var contents = new Buffer("UHOH")
  17. , file = fs.openSync(FILENAME, 'w')
  18. , written = fs.writeSync(file, contents, 0, contents.length, 0)
  19. ;
  20. assert.equals(written, contents.length, "whole buffer was written");
  21. var rc = fs.closeSync(file);
  22. // need this here to avoid dealing with umask complications
  23. fs.chmodSync(FILENAME, '0666');
  24. return rc;
  25. }
  26. function deleteFile() { return fs.unlinkSync(FILENAME); }
  27. function createLink(assert) {
  28. createFile(assert);
  29. fs.symlinkSync(FILENAME, LINKNAME);
  30. if (fs.lchmodSync) {
  31. // This function only exists on BSD systems (like OSX)
  32. fs.lchmodSync(LINKNAME, '0777');
  33. }
  34. }
  35. function deleteLink() {
  36. fs.unlinkSync(LINKNAME);
  37. return deleteFile();
  38. }
  39. function createDirectory(assert) {
  40. fs.mkdirSync(DIRNAME);
  41. assert.ok(fs.existsSync(DIRNAME), "directory was created");
  42. }
  43. function deleteDirectory() { return fs.rmdirSync(DIRNAME); }
  44. function mapIds(username, groupname, callback) {
  45. if (!callback) throw new Error("mapIds requires callback");
  46. if (!username) return callback(new Error("mapIds requires username"));
  47. if (!groupname) return callback(new Error("mapIds requires groupname"));
  48. exec('id -u ' + username, function (error, stdout, stderr) {
  49. if (error) return callback(error);
  50. if (stderr) return callback(new Error(stderr));
  51. var uid = +stdout;
  52. exec('id -g ' + groupname, function (error, stdout, stderr) {
  53. if (error) return callback(error);
  54. if (stderr) return callback(new Error(stderr));
  55. var gid = +stdout;
  56. callback(null, uid, gid);
  57. });
  58. });
  59. }
  60. test("continuation-local state with MakeCallback and fs module", function (t) {
  61. t.plan(33);
  62. var namespace = createNamespace('fs');
  63. namespace.run(function () {
  64. namespace.set('test', 0xabad1dea);
  65. t.test("fs.rename", function (t) {
  66. createFile(t);
  67. namespace.run(function () {
  68. namespace.set('test', 'rename');
  69. t.equal(namespace.get('test'), 'rename', "state has been mutated");
  70. fs.rename(FILENAME, '__renamed', function (error) {
  71. t.notOk(error, "renaming shouldn't error");
  72. t.equal(namespace.get('test'), 'rename',
  73. "mutated state has persisted to fs.rename's callback");
  74. fs.unlinkSync('__renamed');
  75. t.end();
  76. });
  77. });
  78. });
  79. t.test("fs.truncate", function (t) {
  80. // truncate -> ftruncate in Node > 0.8.x
  81. if (!fs.ftruncate) return t.end();
  82. createFile(t);
  83. namespace.run(function () {
  84. namespace.set('test', 'truncate');
  85. t.equal(namespace.get('test'), 'truncate', "state has been mutated");
  86. fs.truncate(FILENAME, 0, function (error) {
  87. t.notOk(error, "truncation shouldn't error");
  88. var stats = fs.statSync(FILENAME);
  89. t.equal(stats.size, 0, "file has been truncated");
  90. t.equal(namespace.get('test'), 'truncate',
  91. "mutated state has persisted to fs.truncate's callback");
  92. deleteFile();
  93. t.end();
  94. });
  95. });
  96. });
  97. t.test("fs.ftruncate", function (t) {
  98. createFile(t);
  99. // truncate -> ftruncate in Node > 0.8.x
  100. var truncate = fs.ftruncate ? fs.ftruncate : fs.truncate;
  101. namespace.run(function () {
  102. namespace.set('test', 'ftruncate');
  103. t.equal(namespace.get('test'), 'ftruncate', "state has been mutated");
  104. var file = fs.openSync(FILENAME, 'w');
  105. truncate(file, 0, function (error) {
  106. t.notOk(error, "truncation shouldn't error");
  107. fs.closeSync(file);
  108. var stats = fs.statSync(FILENAME);
  109. t.equal(stats.size, 0, "file has been truncated");
  110. t.equal(namespace.get('test'), 'ftruncate',
  111. "mutated state has persisted to fs.ftruncate's callback");
  112. deleteFile();
  113. t.end();
  114. });
  115. });
  116. });
  117. t.test("fs.chown", function (t) {
  118. createFile(t);
  119. mapIds('daemon', 'daemon', function (error, uid, gid) {
  120. t.notOk(error, "looking up uid & gid shouldn't error");
  121. t.ok(uid, "uid for daemon was found");
  122. t.ok(gid, "gid for daemon was found");
  123. namespace.run(function () {
  124. namespace.set('test', 'chown');
  125. t.equal(namespace.get('test'), 'chown', "state has been mutated");
  126. fs.chown(FILENAME, uid, gid, function (error) {
  127. t.ok(error, "changing ownership will error for non-root users");
  128. t.equal(namespace.get('test'), 'chown',
  129. "mutated state has persisted to fs.chown's callback");
  130. deleteFile();
  131. t.end();
  132. });
  133. });
  134. });
  135. });
  136. t.test("fs.fchown", function (t) {
  137. createFile(t);
  138. mapIds('daemon', 'daemon', function (error, uid, gid) {
  139. t.notOk(error, "looking up uid & gid shouldn't error");
  140. t.ok(uid, "uid for daemon was found");
  141. t.ok(gid, "gid for daemon was found");
  142. namespace.run(function () {
  143. namespace.set('test', 'fchown');
  144. t.equal(namespace.get('test'), 'fchown', "state has been mutated");
  145. var file = fs.openSync(FILENAME, 'w');
  146. fs.fchown(file, uid, gid, function (error) {
  147. t.ok(error, "changing ownership will error for non-root users");
  148. t.equal(namespace.get('test'), 'fchown',
  149. "mutated state has persisted to fs.fchown's callback");
  150. fs.closeSync(file);
  151. deleteFile();
  152. t.end();
  153. });
  154. });
  155. });
  156. });
  157. t.test("fs.lchown", function (t) {
  158. if (!fs.lchown) return t.end();
  159. createLink(t);
  160. mapIds('daemon', 'daemon', function (error, uid, gid) {
  161. t.notOk(error, "looking up uid & gid shouldn't error");
  162. t.ok(uid, "uid for daemon was found");
  163. t.ok(gid, "gid for daemon was found");
  164. namespace.run(function () {
  165. namespace.set('test', 'lchown');
  166. t.equal(namespace.get('test'), 'lchown', "state has been mutated");
  167. fs.lchown(LINKNAME, uid, gid, function (error) {
  168. t.ok(error, "changing ownership will error for non-root users");
  169. t.equal(namespace.get('test'), 'lchown',
  170. "mutated state has persisted to fs.lchown's callback");
  171. deleteLink();
  172. t.end();
  173. });
  174. });
  175. });
  176. });
  177. t.test("fs.chmod", function (t) {
  178. createFile(t);
  179. namespace.run(function () {
  180. namespace.set('test', 'chmod');
  181. t.equal(namespace.get('test'), 'chmod', "state has been mutated");
  182. fs.chmod(FILENAME, '0700', function (error) {
  183. t.notOk(error, "changing mode shouldn't error");
  184. t.equal(namespace.get('test'), 'chmod',
  185. "mutated state has persisted to fs.chmod's callback");
  186. var stats = fs.statSync(FILENAME);
  187. t.equal(stats.mode.toString(8), '100700', "extra access bits are stripped");
  188. deleteFile();
  189. t.end();
  190. });
  191. });
  192. });
  193. t.test("fs.fchmod", function (t) {
  194. createFile(t);
  195. namespace.run(function () {
  196. namespace.set('test', 'fchmod');
  197. t.equal(namespace.get('test'), 'fchmod', "state has been mutated");
  198. var file = fs.openSync(FILENAME, 'w+');
  199. fs.fchmod(file, '0700', function (error) {
  200. t.notOk(error, "changing mode shouldn't error");
  201. t.equal(namespace.get('test'), 'fchmod',
  202. "mutated state has persisted to fs.fchmod's callback");
  203. fs.closeSync(file);
  204. var stats = fs.statSync(FILENAME);
  205. t.equal(stats.mode.toString(8), '100700', "extra access bits are stripped");
  206. deleteFile();
  207. t.end();
  208. });
  209. });
  210. });
  211. t.test("fs.lchmod", function (t) {
  212. if (!fs.lchmod) return t.end();
  213. createLink(t);
  214. namespace.run(function () {
  215. namespace.set('test', 'lchmod');
  216. t.equal(namespace.get('test'), 'lchmod', "state has been mutated");
  217. fs.lchmod(LINKNAME, '0700', function (error) {
  218. t.notOk(error, "changing mode shouldn't error");
  219. t.equal(namespace.get('test'), 'lchmod',
  220. "mutated state has persisted to fs.lchmod's callback");
  221. var stats = fs.lstatSync(LINKNAME);
  222. t.equal(stats.mode.toString(8), '120700', "extra access bits are stripped");
  223. deleteLink();
  224. t.end();
  225. });
  226. });
  227. });
  228. t.test("fs.stat", function (t) {
  229. createFile(t);
  230. namespace.run(function () {
  231. namespace.set('test', 'stat');
  232. t.equal(namespace.get('test'), 'stat', "state has been mutated");
  233. fs.stat(FILENAME, function (error, stats) {
  234. t.notOk(error, "reading stats shouldn't error");
  235. t.equal(namespace.get('test'), 'stat',
  236. "mutated state has persisted to fs.stat's callback");
  237. t.equal(stats.mode.toString(8), '100666', "permissions should be as created");
  238. deleteFile();
  239. t.end();
  240. });
  241. });
  242. });
  243. t.test("fs.fstat", function (t) {
  244. createFile(t);
  245. namespace.run(function () {
  246. namespace.set('test', 'fstat');
  247. t.equal(namespace.get('test'), 'fstat', "state has been mutated");
  248. var file = fs.openSync(FILENAME, 'r');
  249. fs.fstat(file, function (error, stats) {
  250. t.notOk(error, "reading stats shouldn't error");
  251. t.equal(namespace.get('test'), 'fstat',
  252. "mutated state has persisted to fs.fstat's callback");
  253. t.equal(stats.mode.toString(8), '100666', "permissions should be as created");
  254. fs.closeSync(file);
  255. deleteFile();
  256. t.end();
  257. });
  258. });
  259. });
  260. t.test("fs.lstat", function (t) {
  261. createLink(t);
  262. namespace.run(function () {
  263. namespace.set('test', 'lstat');
  264. t.equal(namespace.get('test'), 'lstat', "state has been mutated");
  265. fs.lstat(LINKNAME, function (error, stats) {
  266. t.notOk(error, "reading stats shouldn't error");
  267. t.equal(namespace.get('test'), 'lstat',
  268. "mutated state has persisted to fs.lstat's callback");
  269. t.equal(
  270. stats.mode.toString(8),
  271. '120777',
  272. "permissions should be as created"
  273. );
  274. deleteLink();
  275. t.end();
  276. });
  277. });
  278. });
  279. t.test("fs.link", function (t) {
  280. createFile(t);
  281. namespace.run(function () {
  282. namespace.set('test', 'link');
  283. t.equal(namespace.get('test'), 'link', "state has been mutated");
  284. fs.link(FILENAME, HARDLINKNAME, function (error) {
  285. t.notOk(error, "creating a link shouldn't error");
  286. t.equal(namespace.get('test'), 'link',
  287. "mutated state has persisted to fs.link's callback");
  288. var orig = fs.statSync(FILENAME)
  289. , linked = fs.statSync(HARDLINKNAME)
  290. ;
  291. t.equal(orig.ino, linked.ino, "entries should point to same file");
  292. t.notOk(fs.unlinkSync(HARDLINKNAME), "link has been removed");
  293. deleteFile();
  294. t.end();
  295. });
  296. });
  297. });
  298. t.test("fs.symlink", function (t) {
  299. createFile(t);
  300. namespace.run(function () {
  301. namespace.set('test', 'symlink');
  302. t.equal(namespace.get('test'), 'symlink', "state has been mutated");
  303. fs.symlink(FILENAME, LINKNAME, function (error) {
  304. t.notOk(error, "creating a symlink shouldn't error");
  305. t.equal(namespace.get('test'), 'symlink',
  306. "mutated state has persisted to fs.symlink's callback");
  307. var pointed = fs.readlinkSync(LINKNAME);
  308. t.equal(pointed, FILENAME, "symlink points back to original file");
  309. t.notOk(fs.unlinkSync(LINKNAME), "symlink has been removed");
  310. deleteFile();
  311. t.end();
  312. });
  313. });
  314. });
  315. t.test("fs.readlink", function (t) {
  316. createLink(t);
  317. namespace.run(function () {
  318. namespace.set('test', 'readlink');
  319. t.equal(namespace.get('test'), 'readlink', "state has been mutated");
  320. fs.readlink(LINKNAME, function (error, pointed) {
  321. t.notOk(error, "reading symlink shouldn't error");
  322. t.equal(namespace.get('test'), 'readlink',
  323. "mutated state has persisted to fs.readlink's callback");
  324. t.equal(pointed, FILENAME, "symlink points back to original file");
  325. deleteLink();
  326. t.end();
  327. });
  328. });
  329. });
  330. t.test("fs.unlink", function (t) {
  331. createFile(t);
  332. namespace.run(function () {
  333. namespace.set('test', 'unlink');
  334. t.equal(namespace.get('test'), 'unlink', "state has been mutated");
  335. fs.unlink(FILENAME, function (error) {
  336. t.notOk(error, "deleting file shouldn't error");
  337. t.equal(namespace.get('test'), 'unlink',
  338. "mutated state has persisted to fs.unlink's callback");
  339. t.notOk(fs.exists(FILENAME), "file should be gone");
  340. t.end();
  341. });
  342. });
  343. });
  344. t.test("fs.realpath", function (t) {
  345. createFile(t);
  346. namespace.run(function () {
  347. namespace.set('test', 'realpath');
  348. t.equal(namespace.get('test'), 'realpath', "state has been mutated");
  349. fs.realpath(FILENAME, function (error, real) {
  350. t.notOk(error, "deleting file shouldn't error");
  351. t.equal(namespace.get('test'), 'realpath',
  352. "mutated state has persisted to fs.realpath's callback");
  353. t.equal(real, path.resolve(FILENAME), "no funny business with the real path");
  354. deleteFile();
  355. t.end();
  356. });
  357. });
  358. });
  359. t.test("fs.mkdir", function (t) {
  360. namespace.run(function () {
  361. namespace.set('test', 'mkdir');
  362. t.equal(namespace.get('test'), 'mkdir', "state has been mutated");
  363. fs.mkdir(DIRNAME, function (error) {
  364. t.notOk(error, "creating directory shouldn't error");
  365. t.equal(namespace.get('test'), 'mkdir',
  366. "mutated state has persisted to fs.mkdir's callback");
  367. t.ok(fs.existsSync(DIRNAME), "directory was created");
  368. fs.rmdirSync(DIRNAME);
  369. t.end();
  370. });
  371. });
  372. });
  373. t.test("fs.rmdir", function (t) {
  374. createDirectory(t);
  375. namespace.run(function () {
  376. namespace.set('test', 'rmdir');
  377. t.equal(namespace.get('test'), 'rmdir', "state has been mutated");
  378. fs.rmdir(DIRNAME, function (error) {
  379. t.notOk(error, "deleting directory shouldn't error");
  380. t.equal(namespace.get('test'), 'rmdir',
  381. "mutated state has persisted to fs.rmdir's callback");
  382. t.notOk(fs.existsSync(DIRNAME), "directory was removed");
  383. t.end();
  384. });
  385. });
  386. });
  387. t.test("fs.readdir", function (t) {
  388. createDirectory(t);
  389. var file1 = fs.openSync(path.join(DIRNAME, 'file1'), 'w');
  390. fs.writeSync(file1, 'one');
  391. fs.closeSync(file1);
  392. var file2 = fs.openSync(path.join(DIRNAME, 'file2'), 'w');
  393. fs.writeSync(file2, 'two');
  394. fs.closeSync(file2);
  395. var file3 = fs.openSync(path.join(DIRNAME, 'file3'), 'w');
  396. fs.writeSync(file3, 'three');
  397. fs.closeSync(file3);
  398. namespace.run(function () {
  399. namespace.set('test', 'readdir');
  400. t.equal(namespace.get('test'), 'readdir', "state has been mutated");
  401. fs.readdir(DIRNAME, function (error, contents) {
  402. t.notOk(error, "reading directory shouldn't error");
  403. t.equal(namespace.get('test'), 'readdir',
  404. "mutated state has persisted to fs.readdir's callback");
  405. t.equal(contents.length, 3, "3 files were found");
  406. fs.unlinkSync(path.join(DIRNAME, 'file1'));
  407. fs.unlinkSync(path.join(DIRNAME, 'file2'));
  408. fs.unlinkSync(path.join(DIRNAME, 'file3'));
  409. deleteDirectory();
  410. t.end();
  411. });
  412. });
  413. });
  414. t.test("fs.watch", function (t) {
  415. createFile(t);
  416. namespace.run(function () {
  417. namespace.set('test', 'watch');
  418. t.equal(namespace.get('test'), 'watch', "state has been mutated");
  419. var watcher = fs.watch(FILENAME,
  420. {persistent : false, interval : 200},
  421. function (event) {
  422. t.equal(namespace.get('test'), 'watch',
  423. "mutated state has persisted to fs.watch's callback");
  424. t.equal(event, 'change', "file was changed");
  425. watcher.close();
  426. process.nextTick(function cleanup() {
  427. deleteFile();
  428. t.end();
  429. });
  430. });
  431. setTimeout(function poke() {
  432. fs.writeFileSync(FILENAME, 'still a test');
  433. }, 20);
  434. });
  435. });
  436. t.test("fs.utimes", function (t) {
  437. createFile(t);
  438. /* utimes(2) takes seconds since the epoch, and Date() deals with
  439. * milliseconds. I just want a date some time in the past.
  440. */
  441. var PASTIME = new Date(Math.floor((Date.now() - 31337) / 1000) * 1000);
  442. namespace.run(function () {
  443. namespace.set('test', 'utimes');
  444. t.equal(namespace.get('test'), 'utimes', "state has been mutated");
  445. var before = fs.statSync(FILENAME);
  446. t.ok(before.atime, "access time of newly-created file set");
  447. t.ok(before.mtime, "modification time of newly-created file set");
  448. fs.utimes(FILENAME, PASTIME, PASTIME, function (error) {
  449. t.notOk(error, "setting utimes shouldn't error");
  450. t.equal(namespace.get('test'), 'utimes',
  451. "mutated state has persisted to fs.utimes's callback");
  452. var after = fs.statSync(FILENAME);
  453. t.deepEqual(after.atime, PASTIME, "access time of newly-created file is reset");
  454. t.deepEqual(after.mtime, PASTIME, "mod time of newly-created file is reset");
  455. t.notDeepEqual(before.atime, after.atime, "access time changed");
  456. t.notDeepEqual(before.mtime, after.mtime, "mod time changed");
  457. deleteFile();
  458. t.end();
  459. });
  460. });
  461. });
  462. t.test("fs.futimes", function (t) {
  463. createFile(t);
  464. /* futimes(2) takes seconds since the epoch, and Date() deals with
  465. * milliseconds. I just want a date some time in the past.
  466. */
  467. var PASTIME = new Date(Math.floor((Date.now() - 0xb33fd) / 1000) * 1000);
  468. namespace.run(function () {
  469. namespace.set('test', 'futimes');
  470. t.equal(namespace.get('test'), 'futimes', "state has been mutated");
  471. var before = fs.statSync(FILENAME);
  472. t.ok(before.atime, "access time of newly-created file set");
  473. t.ok(before.mtime, "modification time of newly-created file set");
  474. var file = fs.openSync(FILENAME, "w+");
  475. fs.futimes(file, PASTIME, PASTIME, function (error) {
  476. t.notOk(error, "setting futimes shouldn't error");
  477. fs.closeSync(file);
  478. t.equal(namespace.get('test'), 'futimes',
  479. "mutated state has persisted to fs.futimes's callback");
  480. var after = fs.statSync(FILENAME);
  481. t.deepEqual(after.atime, PASTIME, "access time of newly-created file is reset");
  482. t.deepEqual(after.mtime, PASTIME, "mod time of newly-created file is reset");
  483. t.notDeepEqual(before.atime, after.atime, "access time changed");
  484. t.notDeepEqual(before.mtime, after.mtime, "mod time changed");
  485. deleteFile();
  486. t.end();
  487. });
  488. });
  489. });
  490. t.test("fs.fsync", function (t) {
  491. createFile(t);
  492. namespace.run(function () {
  493. namespace.set('test', 'fsync');
  494. t.equal(namespace.get('test'), 'fsync', "state has been mutated");
  495. var file = fs.openSync(FILENAME, 'w+');
  496. fs.fsync(file, function (error) {
  497. t.notOk(error, "syncing the file shouldn't error");
  498. t.equal(namespace.get('test'), 'fsync',
  499. "mutated state has persisted to fs.fsync's callback");
  500. fs.closeSync(file);
  501. deleteFile();
  502. t.end();
  503. });
  504. });
  505. });
  506. t.test("fs.open", function (t) {
  507. createFile(t);
  508. namespace.run(function () {
  509. namespace.set('test', 'open');
  510. t.equal(namespace.get('test'), 'open', "state has been mutated");
  511. fs.open(FILENAME, 'r', function (error, file) {
  512. t.notOk(error, "opening the file shouldn't error");
  513. t.equal(namespace.get('test'), 'open',
  514. "mutated state has persisted to fs.open's callback");
  515. var contents = new Buffer(4);
  516. fs.readSync(file, contents, 0, 4, 0);
  517. t.equal(contents.toString(), 'UHOH', "contents are still available");
  518. fs.closeSync(file);
  519. deleteFile();
  520. t.end();
  521. });
  522. });
  523. });
  524. t.test("fs.close", function (t) {
  525. createFile(t);
  526. namespace.run(function () {
  527. namespace.set('test', 'close');
  528. t.equal(namespace.get('test'), 'close', "state has been mutated");
  529. var file = fs.openSync(FILENAME, 'r');
  530. fs.close(file, function (error) {
  531. t.notOk(error, "closing the file shouldn't error");
  532. t.equal(namespace.get('test'), 'close',
  533. "mutated state has persisted to fs.close's callback");
  534. deleteFile();
  535. t.end();
  536. });
  537. });
  538. });
  539. t.test("fs.read", function (t) {
  540. createFile(t);
  541. namespace.run(function () {
  542. namespace.set('test', 'read');
  543. t.equal(namespace.get('test'), 'read', "state has been mutated");
  544. var file = fs.openSync(FILENAME, 'r')
  545. , contents = new Buffer(4)
  546. ;
  547. fs.read(file, contents, 0, 4, 0, function (error) {
  548. t.notOk(error, "reading from the file shouldn't error");
  549. t.equal(namespace.get('test'), 'read',
  550. "mutated state has persisted to fs.read's callback");
  551. t.equal(contents.toString(), 'UHOH', "contents are still available");
  552. fs.closeSync(file);
  553. deleteFile();
  554. t.end();
  555. });
  556. });
  557. });
  558. t.test("fs.write", function (t) {
  559. createFile(t);
  560. namespace.run(function () {
  561. namespace.set('test', 'write');
  562. t.equal(namespace.get('test'), 'write', "state has been mutated");
  563. var file = fs.openSync(FILENAME, 'w')
  564. , contents = new Buffer('yeap')
  565. ;
  566. fs.write(file, contents, 0, 4, 0, function (error) {
  567. t.notOk(error, "writing to the file shouldn't error");
  568. t.equal(namespace.get('test'), 'write',
  569. "mutated state has persisted to fs.write's callback");
  570. fs.closeSync(file);
  571. var readback = fs.readFileSync(FILENAME);
  572. t.equal(readback.toString(), 'yeap', "contents are still available");
  573. deleteFile();
  574. t.end();
  575. });
  576. });
  577. });
  578. t.test("fs.readFile", function (t) {
  579. createFile(t);
  580. namespace.run(function () {
  581. namespace.set('test', 'readFile');
  582. t.equal(namespace.get('test'), 'readFile', "state has been mutated");
  583. fs.readFile(FILENAME, function (error, contents) {
  584. t.notOk(error, "reading from the file shouldn't error");
  585. t.equal(namespace.get('test'), 'readFile',
  586. "mutated state has persisted to fs.readFile's callback");
  587. t.equal(contents.toString(), 'UHOH', "contents are still available");
  588. deleteFile();
  589. t.end();
  590. });
  591. });
  592. });
  593. t.test("fs.writeFile", function (t) {
  594. createFile(t);
  595. namespace.run(function () {
  596. namespace.set('test', 'writeFile');
  597. t.equal(namespace.get('test'), 'writeFile', "state has been mutated");
  598. fs.writeFile(FILENAME, 'woopwoop', function (error) {
  599. t.notOk(error, "rewriting the file shouldn't error");
  600. t.equal(namespace.get('test'), 'writeFile',
  601. "mutated state has persisted to fs.writeFile's callback");
  602. var readback = fs.readFileSync(FILENAME);
  603. t.equal(readback.toString(), 'woopwoop', "rewritten contents are available");
  604. deleteFile();
  605. t.end();
  606. });
  607. });
  608. });
  609. t.test("fs.appendFile", function (t) {
  610. createFile(t);
  611. namespace.run(function () {
  612. namespace.set('test', 'appendFile');
  613. t.equal(namespace.get('test'), 'appendFile', "state has been mutated");
  614. fs.appendFile(FILENAME, '/jk', function (error) {
  615. t.notOk(error, "appending to the file shouldn't error");
  616. t.equal(namespace.get('test'), 'appendFile',
  617. "mutated state has persisted to fs.appendFile's callback");
  618. var readback = fs.readFileSync(FILENAME);
  619. t.equal(readback.toString(), 'UHOH/jk',
  620. "appended contents are still available");
  621. deleteFile();
  622. t.end();
  623. });
  624. });
  625. });
  626. t.test("fs.exists", function (t) {
  627. createFile(t);
  628. namespace.run(function () {
  629. namespace.set('test', 'exists');
  630. t.equal(namespace.get('test'), 'exists', "state has been mutated");
  631. fs.exists(FILENAME, function (yep) {
  632. t.equal(namespace.get('test'), 'exists',
  633. "mutated state has persisted to fs.exists's callback");
  634. t.ok(yep, "precreated file does indeed exist.");
  635. fs.exists('NOPENOWAY', function (nope) {
  636. t.equal(namespace.get('test'), 'exists',
  637. "mutated state continues to persist to fs.exists's second callback");
  638. t.notOk(nope, "nonexistent file doesn't exist.");
  639. deleteFile();
  640. t.end();
  641. });
  642. });
  643. });
  644. });
  645. t.test("fs.watchFile", function (t) {
  646. createFile(t);
  647. namespace.run(function () {
  648. namespace.set('test', 'watchFile');
  649. t.equal(namespace.get('test'), 'watchFile', "state has been mutated");
  650. var options = {
  651. persistent: true,
  652. interval: 20
  653. };
  654. fs.watchFile(FILENAME, options, function (before, after) {
  655. t.equal(namespace.get('test'), 'watchFile',
  656. "mutated state has persisted to fs.watchFile's callback");
  657. t.ok(before.ino, "file has an entry");
  658. t.equal(before.ino, after.ino, "file is at the same location");
  659. fs.unwatchFile(FILENAME);
  660. process.nextTick(function () {
  661. deleteFile();
  662. t.end();
  663. });
  664. });
  665. setTimeout(function poke() {
  666. fs.appendFileSync(FILENAME, 'still a test');
  667. }, 20);
  668. });
  669. });
  670. });
  671. });