test-sftp.js 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  1. var SFTPStream = require('../lib/sftp');
  2. var Stats = SFTPStream.Stats;
  3. var STATUS_CODE = SFTPStream.STATUS_CODE;
  4. var OPEN_MODE = SFTPStream.OPEN_MODE;
  5. var constants = require('constants');
  6. var basename = require('path').basename;
  7. var assert = require('assert');
  8. var group = basename(__filename, '.js') + '/';
  9. var t = -1;
  10. var tests = [
  11. // successful client requests
  12. { run: function() {
  13. setup(this);
  14. var self = this;
  15. var what = this.what;
  16. var client = this.client;
  17. var server = this.server;
  18. this.onReady = function() {
  19. var path_ = '/tmp/foo.txt';
  20. var handle_ = new Buffer('node.js');
  21. server.on('OPEN', function(id, path, pflags, attrs) {
  22. assert(++self.state.requests === 1,
  23. makeMsg(what, 'Saw too many requests'));
  24. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  25. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  26. assert(pflags === (OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE),
  27. makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags)));
  28. server.handle(id, handle_);
  29. server.end();
  30. });
  31. client.open(path_, 'w', function(err, handle) {
  32. assert(++self.state.responses === 1,
  33. makeMsg(what, 'Saw too many responses'));
  34. assert(!err, makeMsg(what, 'Unexpected open() error: ' + err));
  35. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  36. });
  37. };
  38. },
  39. what: 'open'
  40. },
  41. { run: function() {
  42. setup(this);
  43. var self = this;
  44. var what = this.what;
  45. var client = this.client;
  46. var server = this.server;
  47. this.onReady = function() {
  48. var handle_ = new Buffer('node.js');
  49. server.on('CLOSE', function(id, handle) {
  50. assert(++self.state.requests === 1,
  51. makeMsg(what, 'Saw too many requests'));
  52. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  53. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  54. server.status(id, STATUS_CODE.OK);
  55. server.end();
  56. });
  57. client.close(handle_, function(err) {
  58. assert(++self.state.responses === 1,
  59. makeMsg(what, 'Saw too many responses'));
  60. assert(!err, makeMsg(what, 'Unexpected close() error: ' + err));
  61. });
  62. };
  63. },
  64. what: 'close'
  65. },
  66. { run: function() {
  67. setup(this);
  68. var self = this;
  69. var what = this.what;
  70. var client = this.client;
  71. var server = this.server;
  72. this.onReady = function() {
  73. var handle_ = new Buffer('node.js');
  74. var expected = new Buffer('node.jsnode.jsnode.jsnode.jsnode.jsnode.js');
  75. var buffer = new Buffer(expected.length);
  76. buffer.fill(0);
  77. server.on('READ', function(id, handle, offset, len) {
  78. assert(++self.state.requests <= 2,
  79. makeMsg(what, 'Saw too many requests'));
  80. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  81. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  82. assert(offset === 5, makeMsg(what, 'Wrong read offset: ' + offset));
  83. assert(len === buffer.length, makeMsg(what, 'Wrong read len: ' + len));
  84. server.data(id, expected);
  85. server.end();
  86. });
  87. client.readData(handle_, buffer, 0, buffer.length, 5, clientReadCb);
  88. function clientReadCb(err, code) {
  89. assert(++self.state.responses <= 2,
  90. makeMsg(what, 'Saw too many responses'));
  91. assert(!err, makeMsg(what, 'Unexpected readData() error: ' + err));
  92. assert.deepEqual(buffer,
  93. expected,
  94. makeMsg(what, 'read data mismatch'));
  95. }
  96. };
  97. },
  98. what: 'readData'
  99. },
  100. { run: function() {
  101. setup(this);
  102. var self = this;
  103. var what = this.what;
  104. var client = this.client;
  105. var server = this.server;
  106. this.onReady = function() {
  107. var handle_ = new Buffer('node.js');
  108. var buf = new Buffer('node.jsnode.jsnode.jsnode.jsnode.jsnode.js');
  109. server.on('WRITE', function(id, handle, offset, data) {
  110. assert(++self.state.requests === 1,
  111. makeMsg(what, 'Saw too many requests'));
  112. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  113. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  114. assert(offset === 5, makeMsg(what, 'Wrong write offset: ' + offset));
  115. assert.deepEqual(data, buf, makeMsg(what, 'write data mismatch'));
  116. server.status(id, STATUS_CODE.OK);
  117. server.end();
  118. });
  119. client.writeData(handle_, buf, 0, buf.length, 5, function(err, nb) {
  120. assert(++self.state.responses === 1,
  121. makeMsg(what, 'Saw too many responses'));
  122. assert(!err, makeMsg(what, 'Unexpected writeData() error: ' + err));
  123. assert.equal(nb, buf.length);
  124. });
  125. };
  126. },
  127. what: 'write'
  128. },
  129. { run: function() {
  130. setup(this);
  131. var self = this;
  132. var what = this.what;
  133. var client = this.client;
  134. var server = this.server;
  135. this.onReady = function() {
  136. var handle_ = new Buffer('node.js');
  137. var buf = new Buffer(3 * 32 * 1024);
  138. server.on('WRITE', function(id, handle, offset, data) {
  139. ++self.state.requests;
  140. assert.equal(id,
  141. self.state.requests - 1,
  142. makeMsg(what, 'Wrong request id: ' + id));
  143. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  144. assert.equal(offset,
  145. (self.state.requests - 1) * 32 * 1024,
  146. makeMsg(what, 'Wrong write offset: ' + offset));
  147. assert((offset + data.length) <= buf.length);
  148. assert.deepEqual(data,
  149. buf.slice(offset, offset + data.length),
  150. makeMsg(what, 'write data mismatch'));
  151. server.status(id, STATUS_CODE.OK);
  152. if (self.state.requests === 3)
  153. server.end();
  154. });
  155. client.writeData(handle_, buf, 0, buf.length, 0, function(err, nb) {
  156. ++self.state.responses;
  157. assert(!err, makeMsg(what, 'Unexpected writeData() error: ' + err));
  158. assert.equal(nb, buf.length);
  159. });
  160. };
  161. },
  162. expected: {
  163. requests: 3,
  164. responses: 1
  165. },
  166. what: 'write (overflow)'
  167. },
  168. { run: function() {
  169. setup(this);
  170. var self = this;
  171. var what = this.what;
  172. var client = this.client;
  173. var server = this.server;
  174. this.onReady = function() {
  175. var path_ = '/foo/bar/baz';
  176. var attrs_ = new Stats({
  177. size: 10 * 1024,
  178. uid: 9001,
  179. gid: 9001,
  180. atime: (Date.now() / 1000) | 0,
  181. mtime: (Date.now() / 1000) | 0
  182. });
  183. server.on('LSTAT', function(id, path) {
  184. assert(++self.state.requests === 1,
  185. makeMsg(what, 'Saw too many requests'));
  186. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  187. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  188. server.attrs(id, attrs_);
  189. server.end();
  190. });
  191. client.lstat(path_, function(err, attrs) {
  192. assert(++self.state.responses === 1,
  193. makeMsg(what, 'Saw too many responses'));
  194. assert(!err, makeMsg(what, 'Unexpected lstat() error: ' + err));
  195. assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch'));
  196. });
  197. };
  198. },
  199. what: 'lstat'
  200. },
  201. { run: function() {
  202. setup(this);
  203. var self = this;
  204. var what = this.what;
  205. var client = this.client;
  206. var server = this.server;
  207. this.onReady = function() {
  208. var handle_ = new Buffer('node.js');
  209. var attrs_ = new Stats({
  210. size: 10 * 1024,
  211. uid: 9001,
  212. gid: 9001,
  213. atime: (Date.now() / 1000) | 0,
  214. mtime: (Date.now() / 1000) | 0
  215. });
  216. server.on('FSTAT', function(id, handle) {
  217. assert(++self.state.requests === 1,
  218. makeMsg(what, 'Saw too many requests'));
  219. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  220. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  221. server.attrs(id, attrs_);
  222. server.end();
  223. });
  224. client.fstat(handle_, function(err, attrs) {
  225. assert(++self.state.responses === 1,
  226. makeMsg(what, 'Saw too many responses'));
  227. assert(!err, makeMsg(what, 'Unexpected fstat() error: ' + err));
  228. assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch'));
  229. });
  230. };
  231. },
  232. what: 'fstat'
  233. },
  234. { run: function() {
  235. setup(this);
  236. var self = this;
  237. var what = this.what;
  238. var client = this.client;
  239. var server = this.server;
  240. this.onReady = function() {
  241. var path_ = '/foo/bar/baz';
  242. var attrs_ = new Stats({
  243. uid: 9001,
  244. gid: 9001,
  245. atime: (Date.now() / 1000) | 0,
  246. mtime: (Date.now() / 1000) | 0
  247. });
  248. server.on('SETSTAT', function(id, path, attrs) {
  249. assert(++self.state.requests === 1,
  250. makeMsg(what, 'Saw too many requests'));
  251. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  252. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  253. assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch'));
  254. server.status(id, STATUS_CODE.OK);
  255. server.end();
  256. });
  257. client.setstat(path_, attrs_, function(err) {
  258. assert(++self.state.responses === 1,
  259. makeMsg(what, 'Saw too many responses'));
  260. assert(!err, makeMsg(what, 'Unexpected setstat() error: ' + err));
  261. });
  262. };
  263. },
  264. what: 'setstat'
  265. },
  266. { run: function() {
  267. setup(this);
  268. var self = this;
  269. var what = this.what;
  270. var client = this.client;
  271. var server = this.server;
  272. this.onReady = function() {
  273. var handle_ = new Buffer('node.js');
  274. var attrs_ = new Stats({
  275. uid: 9001,
  276. gid: 9001,
  277. atime: (Date.now() / 1000) | 0,
  278. mtime: (Date.now() / 1000) | 0
  279. });
  280. server.on('FSETSTAT', function(id, handle, attrs) {
  281. assert(++self.state.requests === 1,
  282. makeMsg(what, 'Saw too many requests'));
  283. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  284. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  285. assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch'));
  286. server.status(id, STATUS_CODE.OK);
  287. server.end();
  288. });
  289. client.fsetstat(handle_, attrs_, function(err) {
  290. assert(++self.state.responses === 1,
  291. makeMsg(what, 'Saw too many responses'));
  292. assert(!err, makeMsg(what, 'Unexpected fsetstat() error: ' + err));
  293. });
  294. };
  295. },
  296. what: 'fsetstat'
  297. },
  298. { run: function() {
  299. setup(this);
  300. var self = this;
  301. var what = this.what;
  302. var client = this.client;
  303. var server = this.server;
  304. this.onReady = function() {
  305. var handle_ = new Buffer('node.js');
  306. var path_ = '/tmp';
  307. server.on('OPENDIR', function(id, path) {
  308. assert(++self.state.requests === 1,
  309. makeMsg(what, 'Saw too many requests'));
  310. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  311. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  312. server.handle(id, handle_);
  313. server.end();
  314. });
  315. client.opendir(path_, function(err, handle) {
  316. assert(++self.state.responses === 1,
  317. makeMsg(what, 'Saw too many responses'));
  318. assert(!err, makeMsg(what, 'Unexpected opendir() error: ' + err));
  319. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  320. });
  321. };
  322. },
  323. what: 'opendir'
  324. },
  325. { run: function() {
  326. setup(this);
  327. var self = this;
  328. var what = this.what;
  329. var client = this.client;
  330. var server = this.server;
  331. this.onReady = function() {
  332. var handle_ = new Buffer('node.js');
  333. var list_ = [
  334. { filename: '.',
  335. longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .',
  336. attrs: new Stats({
  337. mode: 0755 | constants.S_IFDIR,
  338. size: 4096,
  339. uid: 9001,
  340. gid: 8001,
  341. atime: 1415599549,
  342. mtime: 1415599590
  343. })
  344. },
  345. { filename: '..',
  346. longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..',
  347. attrs: new Stats({
  348. mode: 0755 | constants.S_IFDIR,
  349. size: 4096,
  350. uid: 0,
  351. gid: 0,
  352. atime: 1368729954,
  353. mtime: 1368729999
  354. })
  355. },
  356. { filename: 'foo',
  357. longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo',
  358. attrs: new Stats({
  359. mode: 0777 | constants.S_IFDIR,
  360. size: 4096,
  361. uid: 9001,
  362. gid: 8001,
  363. atime: 1368729954,
  364. mtime: 1368729999
  365. })
  366. },
  367. { filename: 'bar',
  368. longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar',
  369. attrs: new Stats({
  370. mode: 0644 | constants.S_IFREG,
  371. size: 513901992,
  372. uid: 9001,
  373. gid: 8001,
  374. atime: 1259972199,
  375. mtime: 1259972199
  376. })
  377. }
  378. ];
  379. server.on('READDIR', function(id, handle) {
  380. assert(++self.state.requests === 1,
  381. makeMsg(what, 'Saw too many requests'));
  382. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  383. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  384. server.name(id, list_);
  385. server.end();
  386. });
  387. client.readdir(handle_, function(err, list) {
  388. assert(++self.state.responses === 1,
  389. makeMsg(what, 'Saw too many responses'));
  390. assert(!err, makeMsg(what, 'Unexpected readdir() error: ' + err));
  391. assert.deepEqual(list,
  392. list_.slice(2),
  393. makeMsg(what, 'dir list mismatch'));
  394. });
  395. };
  396. },
  397. what: 'readdir'
  398. },
  399. { run: function() {
  400. setup(this);
  401. var self = this;
  402. var what = this.what;
  403. var client = this.client;
  404. var server = this.server;
  405. this.onReady = function() {
  406. var handle_ = new Buffer('node.js');
  407. var list_ = [
  408. { filename: '.',
  409. longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .',
  410. attrs: new Stats({
  411. mode: 0755 | constants.S_IFDIR,
  412. size: 4096,
  413. uid: 9001,
  414. gid: 8001,
  415. atime: 1415599549,
  416. mtime: 1415599590
  417. })
  418. },
  419. { filename: '..',
  420. longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..',
  421. attrs: new Stats({
  422. mode: 0755 | constants.S_IFDIR,
  423. size: 4096,
  424. uid: 0,
  425. gid: 0,
  426. atime: 1368729954,
  427. mtime: 1368729999
  428. })
  429. },
  430. { filename: 'foo',
  431. longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo',
  432. attrs: new Stats({
  433. mode: 0777 | constants.S_IFDIR,
  434. size: 4096,
  435. uid: 9001,
  436. gid: 8001,
  437. atime: 1368729954,
  438. mtime: 1368729999
  439. })
  440. },
  441. { filename: 'bar',
  442. longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar',
  443. attrs: new Stats({
  444. mode: 0644 | constants.S_IFREG,
  445. size: 513901992,
  446. uid: 9001,
  447. gid: 8001,
  448. atime: 1259972199,
  449. mtime: 1259972199
  450. })
  451. }
  452. ];
  453. server.on('READDIR', function(id, handle) {
  454. assert(++self.state.requests === 1,
  455. makeMsg(what, 'Saw too many requests'));
  456. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  457. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  458. server.name(id, list_);
  459. server.end();
  460. });
  461. client.readdir(handle_, { full: true }, function(err, list) {
  462. assert(++self.state.responses === 1,
  463. makeMsg(what, 'Saw too many responses'));
  464. assert(!err, makeMsg(what, 'Unexpected readdir() error: ' + err));
  465. assert.deepEqual(list, list_, makeMsg(what, 'dir list mismatch'));
  466. });
  467. };
  468. },
  469. what: 'readdir (full)'
  470. },
  471. { run: function() {
  472. setup(this);
  473. var self = this;
  474. var what = this.what;
  475. var client = this.client;
  476. var server = this.server;
  477. this.onReady = function() {
  478. var path_ = '/foo/bar/baz';
  479. server.on('REMOVE', function(id, path) {
  480. assert(++self.state.requests === 1,
  481. makeMsg(what, 'Saw too many requests'));
  482. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  483. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  484. server.status(id, STATUS_CODE.OK);
  485. server.end();
  486. });
  487. client.unlink(path_, function(err) {
  488. assert(++self.state.responses === 1,
  489. makeMsg(what, 'Saw too many responses'));
  490. assert(!err, makeMsg(what, 'Unexpected unlink() error: ' + err));
  491. });
  492. };
  493. },
  494. what: 'remove'
  495. },
  496. { run: function() {
  497. setup(this);
  498. var self = this;
  499. var what = this.what;
  500. var client = this.client;
  501. var server = this.server;
  502. this.onReady = function() {
  503. var path_ = '/foo/bar/baz';
  504. server.on('MKDIR', function(id, path) {
  505. assert(++self.state.requests === 1,
  506. makeMsg(what, 'Saw too many requests'));
  507. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  508. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  509. server.status(id, STATUS_CODE.OK);
  510. server.end();
  511. });
  512. client.mkdir(path_, function(err) {
  513. assert(++self.state.responses === 1,
  514. makeMsg(what, 'Saw too many responses'));
  515. assert(!err, makeMsg(what, 'Unexpected mkdir() error: ' + err));
  516. });
  517. };
  518. },
  519. what: 'mkdir'
  520. },
  521. { run: function() {
  522. setup(this);
  523. var self = this;
  524. var what = this.what;
  525. var client = this.client;
  526. var server = this.server;
  527. this.onReady = function() {
  528. var path_ = '/foo/bar/baz';
  529. server.on('RMDIR', function(id, path) {
  530. assert(++self.state.requests === 1,
  531. makeMsg(what, 'Saw too many requests'));
  532. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  533. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  534. server.status(id, STATUS_CODE.OK);
  535. server.end();
  536. });
  537. client.rmdir(path_, function(err) {
  538. assert(++self.state.responses === 1,
  539. makeMsg(what, 'Saw too many responses'));
  540. assert(!err, makeMsg(what, 'Unexpected rmdir() error: ' + err));
  541. });
  542. };
  543. },
  544. what: 'rmdir'
  545. },
  546. { run: function() {
  547. setup(this);
  548. var self = this;
  549. var what = this.what;
  550. var client = this.client;
  551. var server = this.server;
  552. this.onReady = function() {
  553. var path_ = '/foo/bar/baz';
  554. var name_ = { filename: '/tmp/foo' };
  555. server.on('REALPATH', function(id, path) {
  556. assert(++self.state.requests === 1,
  557. makeMsg(what, 'Saw too many requests'));
  558. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  559. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  560. server.name(id, name_);
  561. server.end();
  562. });
  563. client.realpath(path_, function(err, name) {
  564. assert(++self.state.responses === 1,
  565. makeMsg(what, 'Saw too many responses'));
  566. assert(!err, makeMsg(what, 'Unexpected realpath() error: ' + err));
  567. assert.deepEqual(name, name_.filename, makeMsg(what, 'name mismatch'));
  568. });
  569. };
  570. },
  571. what: 'realpath'
  572. },
  573. { run: function() {
  574. setup(this);
  575. var self = this;
  576. var what = this.what;
  577. var client = this.client;
  578. var server = this.server;
  579. this.onReady = function() {
  580. var path_ = '/foo/bar/baz';
  581. var attrs_ = new Stats({
  582. size: 10 * 1024,
  583. uid: 9001,
  584. gid: 9001,
  585. atime: (Date.now() / 1000) | 0,
  586. mtime: (Date.now() / 1000) | 0
  587. });
  588. server.on('STAT', function(id, path) {
  589. assert(++self.state.requests === 1,
  590. makeMsg(what, 'Saw too many requests'));
  591. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  592. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  593. server.attrs(id, attrs_);
  594. server.end();
  595. });
  596. client.stat(path_, function(err, attrs) {
  597. assert(++self.state.responses === 1,
  598. makeMsg(what, 'Saw too many responses'));
  599. assert(!err, makeMsg(what, 'Unexpected stat() error: ' + err));
  600. assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch'));
  601. });
  602. };
  603. },
  604. what: 'stat'
  605. },
  606. { run: function() {
  607. setup(this);
  608. var self = this;
  609. var what = this.what;
  610. var client = this.client;
  611. var server = this.server;
  612. this.onReady = function() {
  613. var oldPath_ = '/foo/bar/baz';
  614. var newPath_ = '/tmp/foo';
  615. server.on('RENAME', function(id, oldPath, newPath) {
  616. assert(++self.state.requests === 1,
  617. makeMsg(what, 'Saw too many requests'));
  618. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  619. assert(oldPath === oldPath_,
  620. makeMsg(what, 'Wrong old path: ' + oldPath));
  621. assert(newPath === newPath_,
  622. makeMsg(what, 'Wrong new path: ' + newPath));
  623. server.status(id, STATUS_CODE.OK);
  624. server.end();
  625. });
  626. client.rename(oldPath_, newPath_, function(err) {
  627. assert(++self.state.responses === 1,
  628. makeMsg(what, 'Saw too many responses'));
  629. assert(!err, makeMsg(what, 'Unexpected rename() error: ' + err));
  630. });
  631. };
  632. },
  633. what: 'rename'
  634. },
  635. { run: function() {
  636. setup(this);
  637. var self = this;
  638. var what = this.what;
  639. var client = this.client;
  640. var server = this.server;
  641. this.onReady = function() {
  642. var linkPath_ = '/foo/bar/baz';
  643. var name = { filename: '/tmp/foo' };
  644. server.on('READLINK', function(id, linkPath) {
  645. assert(++self.state.requests === 1,
  646. makeMsg(what, 'Saw too many requests'));
  647. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  648. assert(linkPath === linkPath_,
  649. makeMsg(what, 'Wrong link path: ' + linkPath));
  650. server.name(id, name);
  651. server.end();
  652. });
  653. client.readlink(linkPath_, function(err, targetPath) {
  654. assert(++self.state.responses === 1,
  655. makeMsg(what, 'Saw too many responses'));
  656. assert(!err, makeMsg(what, 'Unexpected readlink() error: ' + err));
  657. assert(targetPath === name.filename,
  658. makeMsg(what, 'Wrong target path: ' + targetPath));
  659. });
  660. };
  661. },
  662. what: 'readlink'
  663. },
  664. { run: function() {
  665. setup(this);
  666. var self = this;
  667. var what = this.what;
  668. var client = this.client;
  669. var server = this.server;
  670. this.onReady = function() {
  671. var linkPath_ = '/foo/bar/baz';
  672. var targetPath_ = '/tmp/foo';
  673. server.on('SYMLINK', function(id, linkPath, targetPath) {
  674. assert(++self.state.requests === 1,
  675. makeMsg(what, 'Saw too many requests'));
  676. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  677. assert(linkPath === linkPath_,
  678. makeMsg(what, 'Wrong link path: ' + linkPath));
  679. assert(targetPath === targetPath_,
  680. makeMsg(what, 'Wrong target path: ' + targetPath));
  681. server.status(id, STATUS_CODE.OK);
  682. server.end();
  683. });
  684. client.symlink(targetPath_, linkPath_, function(err) {
  685. assert(++self.state.responses === 1,
  686. makeMsg(what, 'Saw too many responses'));
  687. assert(!err, makeMsg(what, 'Unexpected symlink() error: ' + err));
  688. });
  689. };
  690. },
  691. what: 'symlink'
  692. },
  693. { run: function() {
  694. setup(this);
  695. var self = this;
  696. var what = this.what;
  697. var client = this.client;
  698. var server = this.server;
  699. this.onReady = function() {
  700. var path_ = '/foo/bar/baz';
  701. var handle_ = new Buffer('hi mom!');
  702. var data_ = new Buffer('hello world');
  703. server.once('OPEN', function(id, path, pflags, attrs) {
  704. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  705. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  706. assert(pflags === OPEN_MODE.READ,
  707. makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags)));
  708. server.handle(id, handle_);
  709. }).once('FSTAT', function(id, handle) {
  710. assert(id === 1, makeMsg(what, 'Wrong request id: ' + id));
  711. var attrs = new Stats({
  712. size: data_.length,
  713. uid: 9001,
  714. gid: 9001,
  715. atime: (Date.now() / 1000) | 0,
  716. mtime: (Date.now() / 1000) | 0
  717. });
  718. server.attrs(id, attrs);
  719. }).once('READ', function(id, handle, offset, len) {
  720. assert(id === 2, makeMsg(what, 'Wrong request id: ' + id));
  721. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  722. assert(offset === 0, makeMsg(what, 'Wrong read offset: ' + offset));
  723. server.data(id, data_);
  724. }).once('CLOSE', function(id, handle) {
  725. ++self.state.requests;
  726. assert(id === 3, makeMsg(what, 'Wrong request id: ' + id));
  727. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  728. server.status(id, STATUS_CODE.OK);
  729. server.end();
  730. });
  731. var buf = [];
  732. client.readFile(path_, function(err, buf) {
  733. ++self.state.responses;
  734. assert(!err, makeMsg(what, 'Unexpected error: ' + err));
  735. assert.deepEqual(buf, data_, makeMsg(what, 'data mismatch'));
  736. });
  737. };
  738. },
  739. what: 'readFile'
  740. },
  741. { run: function() {
  742. setup(this);
  743. var self = this;
  744. var what = this.what;
  745. var client = this.client;
  746. var server = this.server;
  747. this.onReady = function() {
  748. var path_ = '/foo/bar/baz';
  749. var handle_ = new Buffer('hi mom!');
  750. var data_ = new Buffer('hello world');
  751. var reads = 0;
  752. server.once('OPEN', function(id, path, pflags, attrs) {
  753. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  754. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  755. assert(pflags === OPEN_MODE.READ,
  756. makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags)));
  757. server.handle(id, handle_);
  758. }).once('FSTAT', function(id, handle) {
  759. assert(id === 1, makeMsg(what, 'Wrong request id: ' + id));
  760. var attrs = new Stats({
  761. uid: 9001,
  762. gid: 9001,
  763. atime: (Date.now() / 1000) | 0,
  764. mtime: (Date.now() / 1000) | 0
  765. });
  766. server.attrs(id, attrs);
  767. }).on('READ', function(id, handle, offset, len) {
  768. assert(++reads <= 2, makeMsg(what, 'Saw too many READs'));
  769. assert(id === 2 || id === 3, makeMsg(what, 'Wrong request id: ' + id));
  770. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  771. switch(id) {
  772. case 2:
  773. assert(offset === 0, makeMsg(what, 'Wrong read offset for first read: ' + offset));
  774. server.data(id, data_);
  775. break;
  776. case 3:
  777. assert(offset === data_.length, makeMsg(what, 'Wrong read offset for second read: ' + offset));
  778. server.status(id, STATUS_CODE.EOF);
  779. break;
  780. }
  781. }).once('CLOSE', function(id, handle) {
  782. ++self.state.requests;
  783. assert(id === 4, makeMsg(what, 'Wrong request id: ' + id));
  784. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  785. server.status(id, STATUS_CODE.OK);
  786. server.end();
  787. });
  788. var buf = [];
  789. client.readFile(path_, function(err, buf) {
  790. ++self.state.responses;
  791. assert(!err, makeMsg(what, 'Unexpected error: ' + err));
  792. assert.deepEqual(buf, data_, makeMsg(what, 'data mismatch'));
  793. });
  794. };
  795. },
  796. what: 'readFile (no size from fstat)'
  797. },
  798. { run: function() {
  799. setup(this);
  800. var self = this;
  801. var what = this.what;
  802. var client = this.client;
  803. var server = this.server;
  804. this.onReady = function() {
  805. var opens = 0;
  806. var reads = 0;
  807. var closes = 0;
  808. var path_ = '/foo/bar/baz';
  809. var handle_ = new Buffer('hi mom!');
  810. var data_ = new Buffer('hello world');
  811. server.on('OPEN', function(id, path, pflags, attrs) {
  812. assert(++opens === 1, makeMsg(what, 'Saw too many OPENs'));
  813. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  814. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  815. assert(pflags === OPEN_MODE.READ,
  816. makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags)));
  817. server.handle(id, handle_);
  818. }).on('READ', function(id, handle, offset, len) {
  819. assert(++reads <= 2, makeMsg(what, 'Saw too many READs'));
  820. assert(id === reads, makeMsg(what, 'Wrong request id: ' + id));
  821. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  822. if (reads === 1) {
  823. assert(offset === 0, makeMsg(what, 'Wrong read offset: ' + offset));
  824. server.data(id, data_);
  825. } else
  826. server.status(id, STATUS_CODE.EOF);
  827. }).on('CLOSE', function(id, handle) {
  828. ++self.state.requests;
  829. assert(++closes === 1, makeMsg(what, 'Saw too many CLOSEs'));
  830. assert(id === 3, makeMsg(what, 'Wrong request id: ' + id));
  831. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  832. server.status(id, STATUS_CODE.OK);
  833. server.end();
  834. });
  835. var buf = [];
  836. client.createReadStream(path_).on('readable', function() {
  837. var chunk;
  838. while ((chunk = this.read()) !== null) {
  839. buf.push(chunk);
  840. }
  841. }).on('end', function() {
  842. assert(++self.state.responses === 1,
  843. makeMsg(what, 'Saw too many responses'));
  844. buf = Buffer.concat(buf);
  845. assert.deepEqual(buf, data_, makeMsg(what, 'data mismatch'));
  846. });
  847. };
  848. },
  849. what: 'ReadStream'
  850. },
  851. { run: function() {
  852. setup(this);
  853. var self = this;
  854. var what = this.what;
  855. var client = this.client;
  856. var server = this.server;
  857. this.onReady = function() {
  858. var opens = 0;
  859. var path_ = '/foo/bar/baz';
  860. var error;
  861. server.on('OPEN', function(id, path, pflags, attrs) {
  862. ++opens;
  863. ++self.state.requests;
  864. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  865. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  866. assert(pflags === OPEN_MODE.READ,
  867. makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags)));
  868. server.status(id, STATUS_CODE.NO_SUCH_FILE);
  869. server.end();
  870. });
  871. client.createReadStream(path_).on('error', function(err) {
  872. error = err;
  873. }).on('close', function() {
  874. assert(opens === 1, makeMsg(what, 'Saw ' + opens + ' OPENs'));
  875. assert(error, makeMsg(what, 'Expected error'));
  876. assert(++self.state.responses === 1,
  877. makeMsg(what, 'Saw too many responses'));
  878. });
  879. };
  880. },
  881. what: 'ReadStream (error)'
  882. },
  883. { run: function() {
  884. setup(this);
  885. var self = this;
  886. var what = this.what;
  887. var client = this.client;
  888. var server = this.server;
  889. this.onReady = function() {
  890. var opens = 0;
  891. var writes = 0;
  892. var closes = 0;
  893. var fsetstat = false;
  894. var path_ = '/foo/bar/baz';
  895. var handle_ = new Buffer('hi mom!');
  896. var data_ = new Buffer('hello world');
  897. var expFlags = OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE;
  898. server.on('OPEN', function(id, path, pflags, attrs) {
  899. assert(++opens === 1, makeMsg(what, 'Saw too many OPENs'));
  900. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  901. assert(path === path_, makeMsg(what, 'Wrong path: ' + path));
  902. assert(pflags === expFlags,
  903. makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags)));
  904. server.handle(id, handle_);
  905. }).once('FSETSTAT', function(id, handle, attrs) {
  906. fsetstat = true;
  907. assert(id === 1, makeMsg(what, 'Wrong request id: ' + id));
  908. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  909. assert.strictEqual(attrs.mode,
  910. parseInt('0666', 8),
  911. makeMsg(what, 'Wrong file mode'));
  912. server.status(id, STATUS_CODE.OK);
  913. }).on('WRITE', function(id, handle, offset, data) {
  914. assert(++writes <= 3, makeMsg(what, 'Saw too many WRITEs'));
  915. assert(id === writes + 1, makeMsg(what, 'Wrong request id: ' + id));
  916. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  917. assert(offset === ((writes - 1) * data_.length),
  918. makeMsg(what, 'Wrong write offset: ' + offset));
  919. assert.deepEqual(data, data_, makeMsg(what, 'Wrong data'));
  920. server.status(id, STATUS_CODE.OK);
  921. }).on('CLOSE', function(id, handle) {
  922. ++self.state.requests;
  923. assert(++closes === 1, makeMsg(what, 'Saw too many CLOSEs'));
  924. assert(id === 5, makeMsg(what, 'Wrong request id: ' + id));
  925. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  926. server.status(id, STATUS_CODE.OK);
  927. server.end();
  928. }).on('end', function() {
  929. assert(++self.state.responses === 1,
  930. makeMsg(what, 'Saw too many responses'));
  931. assert(opens === 1, makeMsg(what, 'Wrong OPEN count'));
  932. assert(writes === 3, makeMsg(what, 'Wrong WRITE count'));
  933. assert(closes === 1, makeMsg(what, 'Wrong CLOSE count'));
  934. assert(fsetstat, makeMsg(what, 'Expected FSETSTAT'));
  935. });
  936. var writer = client.createWriteStream(path_);
  937. if (writer.cork)
  938. writer.cork();
  939. writer.write(data_);
  940. writer.write(data_);
  941. writer.write(data_);
  942. if (writer.uncork)
  943. writer.uncork();
  944. writer.end();
  945. };
  946. },
  947. what: 'WriteStream'
  948. },
  949. // other client request scenarios
  950. { run: function() {
  951. setup(this);
  952. var self = this;
  953. var what = this.what;
  954. var client = this.client;
  955. var server = this.server;
  956. this.onReady = function() {
  957. var handle_ = new Buffer('node.js');
  958. server.on('READDIR', function(id, handle) {
  959. assert(++self.state.requests === 1,
  960. makeMsg(what, 'Saw too many requests'));
  961. assert(id === 0, makeMsg(what, 'Wrong request id: ' + id));
  962. assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch'));
  963. server.status(id, STATUS_CODE.EOF);
  964. server.end();
  965. });
  966. client.readdir(handle_, function(err, list) {
  967. assert(++self.state.responses === 1,
  968. makeMsg(what, 'Saw too many responses'));
  969. assert(err && err.code === STATUS_CODE.EOF,
  970. makeMsg(what, 'Expected EOF, got: ' + err));
  971. });
  972. };
  973. },
  974. what: 'readdir (EOF)'
  975. },
  976. { run: function() {
  977. setup(this);
  978. var self = this;
  979. var what = this.what;
  980. var client = this.client;
  981. var server = this.server;
  982. this.onReady = function() {
  983. var path_ = '/tmp/foo.txt';
  984. var reqs = 0;
  985. var continues = 0;
  986. client.unpipe(server);
  987. function clientCb(err, handle) {
  988. assert(++self.state.responses <= reqs,
  989. makeMsg(what, 'Saw too many responses'));
  990. if (self.state.responses === reqs) {
  991. assert(continues === 1, makeMsg(what, 'no continue event seen'));
  992. server.end();
  993. }
  994. }
  995. client.on('continue', function() {
  996. assert(++continues === 1, makeMsg(what, 'saw > 1 continue event'));
  997. });
  998. while (true) {
  999. ++reqs;
  1000. if (!client.open(path_, 'w', clientCb))
  1001. break;
  1002. }
  1003. client.pipe(server);
  1004. };
  1005. },
  1006. expected: {
  1007. requests: -1,
  1008. responses: -1
  1009. },
  1010. what: '"continue" event after push() === false'
  1011. },
  1012. { run: function() {
  1013. var self = this;
  1014. var client = new SFTPStream();
  1015. client.once('ready', function() {
  1016. client.open('/foo/bar', 'w', function(err, handle) {
  1017. assert(err, 'Expected error');
  1018. assert.strictEqual(err.code, 4);
  1019. assert.strictEqual(err.message, 'Uh oh');
  1020. assert.strictEqual(err.lang, '');
  1021. next();
  1022. });
  1023. client.write(new Buffer([
  1024. 0, 0, 0, 18,
  1025. 101,
  1026. 0, 0, 0, 0,
  1027. 0, 0, 0, SFTPStream.STATUS_CODE.FAILURE,
  1028. 0, 0, 0, 5, 85, 104, 32, 111, 104
  1029. ]));
  1030. });
  1031. client.write(new Buffer([
  1032. 0, 0, 0, 5,
  1033. 2,
  1034. 0, 0, 0, 3
  1035. ]));
  1036. },
  1037. what: 'Can parse status response without language'
  1038. },
  1039. { run: function() {
  1040. var self = this;
  1041. var client = new SFTPStream();
  1042. client.once('ready', function() {
  1043. client.open('/foo/bar', 'w', function(err, handle) {
  1044. assert(err, 'Expected error');
  1045. assert.strictEqual(err.code, 4);
  1046. assert.strictEqual(err.message, 'Failure');
  1047. assert.strictEqual(err.lang, '');
  1048. next();
  1049. });
  1050. client.write(new Buffer([
  1051. 0, 0, 0, 9,
  1052. 101,
  1053. 0, 0, 0, 0,
  1054. 0, 0, 0, SFTPStream.STATUS_CODE.FAILURE
  1055. ]));
  1056. });
  1057. client.write(new Buffer([
  1058. 0, 0, 0, 5,
  1059. 2,
  1060. 0, 0, 0, 3
  1061. ]));
  1062. },
  1063. what: 'Can parse status response without message'
  1064. },
  1065. { run: function() {
  1066. var self = this;
  1067. var err;
  1068. var client = new SFTPStream();
  1069. client.once('ready', function() {
  1070. assert(false, 'Handshake should not succeed');
  1071. }).once('error', function(err_) {
  1072. err = err_;
  1073. }).once('end', function() {
  1074. assert.strictEqual(err && err.message,
  1075. 'Unexpected packet before version');
  1076. next();
  1077. });
  1078. client.write(new Buffer([
  1079. 1, 2, 3, 4,
  1080. 5,
  1081. 6, 7, 8, 9
  1082. ]));
  1083. },
  1084. what: 'End SFTP stream on bad handshake (client)'
  1085. },
  1086. { run: function() {
  1087. var self = this;
  1088. var err;
  1089. var client = new SFTPStream({ server: true });
  1090. client.once('ready', function() {
  1091. assert(false, 'Handshake should not succeed');
  1092. }).once('error', function(err_) {
  1093. err = err_;
  1094. }).once('end', function() {
  1095. assert.strictEqual(err && err.message,
  1096. 'Unexpected packet before init');
  1097. next();
  1098. });
  1099. client.write(new Buffer([
  1100. 1, 2, 3, 4,
  1101. 5,
  1102. 6, 7, 8, 9
  1103. ]));
  1104. },
  1105. what: 'End SFTP stream on bad handshake (server)'
  1106. },
  1107. ];
  1108. function setup(self) {
  1109. var expectedRequests = (self.expected && self.expected.requests) || 1;
  1110. var expectedResponses = (self.expected && self.expected.responses) || 1;
  1111. var clientEnded = false;
  1112. var serverEnded = false;
  1113. self.state = {
  1114. clientReady: false,
  1115. serverReady: false,
  1116. requests: 0,
  1117. responses: 0
  1118. };
  1119. self.client = new SFTPStream();
  1120. self.server = new SFTPStream({ server: true });
  1121. self.server.on('error', onError)
  1122. .on('ready', onReady)
  1123. .on('end', onEnd);
  1124. self.client.on('error', onError)
  1125. .on('ready', onReady)
  1126. .on('end', onEnd);
  1127. function onError(err) {
  1128. var which = (this === self.server ? 'server' : 'client');
  1129. assert(false, makeMsg(self.what, 'Unexpected ' + which + ' error: ' + err));
  1130. }
  1131. function onReady() {
  1132. if (this === self.client) {
  1133. assert(!self.state.clientReady,
  1134. makeMsg(self.what, 'Received multiple ready events for client'));
  1135. self.state.clientReady = true;
  1136. } else {
  1137. assert(!self.state.serverReady,
  1138. makeMsg(self.what, 'Received multiple ready events for server'));
  1139. self.state.serverReady = true;
  1140. }
  1141. if (self.state.clientReady && self.state.serverReady)
  1142. self.onReady && self.onReady();
  1143. }
  1144. function onEnd() {
  1145. if (this === self.client) {
  1146. assert(!clientEnded,
  1147. makeMsg(self.what, 'Received multiple close events for client'));
  1148. clientEnded = true;
  1149. } else {
  1150. assert(!serverEnded,
  1151. makeMsg(self.what, 'Received multiple close events for server'));
  1152. serverEnded = true;
  1153. }
  1154. if (clientEnded && serverEnded) {
  1155. var msg;
  1156. if (expectedRequests > 0) {
  1157. msg = 'Expected ' + expectedRequests + ' request(s) but received '
  1158. + self.state.requests;
  1159. assert(self.state.requests === expectedRequests,
  1160. makeMsg(self.what, msg));
  1161. }
  1162. if (expectedResponses > 0) {
  1163. msg = 'Expected ' + expectedResponses + ' response(s) but received '
  1164. + self.state.responses;
  1165. assert(self.state.responses === expectedResponses,
  1166. makeMsg(self.what, msg));
  1167. }
  1168. next();
  1169. }
  1170. }
  1171. process.nextTick(function() {
  1172. self.client.pipe(self.server).pipe(self.client);
  1173. });
  1174. }
  1175. function flagsToHuman(flags) {
  1176. var ret = [];
  1177. for (var i = 0, keys = Object.keys(OPEN_MODE), len = keys.length; i < len; ++i)
  1178. if (flags & OPEN_MODE[keys[i]])
  1179. ret.push(keys[i]);
  1180. return ret.join(' | ');
  1181. }
  1182. function next() {
  1183. if (++t === tests.length)
  1184. return;
  1185. var v = tests[t];
  1186. v.run.call(v);
  1187. }
  1188. function makeMsg(what, msg) {
  1189. return '[' + group + what + ']: ' + msg;
  1190. }
  1191. process.once('exit', function() {
  1192. assert(t === tests.length,
  1193. makeMsg('_exit',
  1194. 'Only finished ' + t + '/' + tests.length + ' tests'));
  1195. });
  1196. next();